vfs: Add struct vfs_open_how.resolve
[samba.git] / source3 / modules / vfs_streams_xattr.c
1 /*
2  * Store streams in xattrs
3  *
4  * Copyright (C) Volker Lendecke, 2008
5  *
6  * Partly based on James Peach's Darwin module, which is
7  *
8  * Copyright (C) James Peach 2006-2007
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include "includes.h"
25 #include "smbd/smbd.h"
26 #include "system/filesys.h"
27 #include "lib/util/tevent_unix.h"
28 #include "librpc/gen_ndr/ioctl.h"
29 #include "hash_inode.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_VFS
33
34 struct streams_xattr_config {
35         const char *prefix;
36         size_t prefix_len;
37         bool store_stream_type;
38 };
39
40 struct stream_io {
41         char *base;
42         char *xattr_name;
43         void *fsp_name_ptr;
44         files_struct *fsp;
45         vfs_handle_struct *handle;
46 };
47
48 static ssize_t get_xattr_size_fsp(struct files_struct *fsp,
49                                   const char *xattr_name)
50 {
51         NTSTATUS status;
52         struct ea_struct ea;
53         ssize_t result;
54
55         status = get_ea_value_fsp(talloc_tos(),
56                                   fsp,
57                                   xattr_name,
58                                   &ea);
59         if (!NT_STATUS_IS_OK(status)) {
60                 return -1;
61         }
62
63         result = ea.value.length-1;
64         TALLOC_FREE(ea.value.data);
65         return result;
66 }
67
68 /**
69  * Given a stream name, populate xattr_name with the xattr name to use for
70  * accessing the stream.
71  */
72 static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
73                                        TALLOC_CTX *ctx,
74                                        const char *stream_name,
75                                        char **xattr_name)
76 {
77         char *sname;
78         char *stype;
79         struct streams_xattr_config *config;
80
81         SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
82                                 return NT_STATUS_UNSUCCESSFUL);
83
84         sname = talloc_strdup(ctx, stream_name + 1);
85         if (sname == NULL) {
86                 return NT_STATUS_NO_MEMORY;
87         }
88
89         /*
90          * With vfs_fruit option "fruit:encoding = native" we're
91          * already converting stream names that contain illegal NTFS
92          * characters from their on-the-wire Unicode Private Range
93          * encoding to their native ASCII representation.
94          *
95          * As as result the name of xattrs storing the streams (via
96          * vfs_streams_xattr) may contain a colon, so we have to use
97          * strrchr_m() instead of strchr_m() for matching the stream
98          * type suffix.
99          *
100          * In check_path_syntax() we've already ensured the streamname
101          * we got from the client is valid.
102          */
103         stype = strrchr_m(sname, ':');
104
105         if (stype) {
106                 /*
107                  * We only support one stream type: "$DATA"
108                  */
109                 if (strcasecmp_m(stype, ":$DATA") != 0) {
110                         talloc_free(sname);
111                         return NT_STATUS_INVALID_PARAMETER;
112                 }
113
114                 /* Split name and type */
115                 stype[0] = '\0';
116         }
117
118         *xattr_name = talloc_asprintf(ctx, "%s%s%s",
119                                       config->prefix,
120                                       sname,
121                                       config->store_stream_type ? ":$DATA" : "");
122         if (*xattr_name == NULL) {
123                 talloc_free(sname);
124                 return NT_STATUS_NO_MEMORY;
125         }
126
127         DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
128                    stream_name));
129
130         talloc_free(sname);
131         return NT_STATUS_OK;
132 }
133
134 static bool streams_xattr_recheck(struct stream_io *sio)
135 {
136         NTSTATUS status;
137         char *xattr_name = NULL;
138
139         if (sio->fsp->fsp_name == sio->fsp_name_ptr) {
140                 return true;
141         }
142
143         if (sio->fsp->fsp_name->stream_name == NULL) {
144                 /* how can this happen */
145                 errno = EINVAL;
146                 return false;
147         }
148
149         status = streams_xattr_get_name(sio->handle, talloc_tos(),
150                                         sio->fsp->fsp_name->stream_name,
151                                         &xattr_name);
152         if (!NT_STATUS_IS_OK(status)) {
153                 return false;
154         }
155
156         TALLOC_FREE(sio->xattr_name);
157         TALLOC_FREE(sio->base);
158         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp),
159                                         xattr_name);
160         if (sio->xattr_name == NULL) {
161                 DBG_DEBUG("sio->xattr_name==NULL\n");
162                 return false;
163         }
164         TALLOC_FREE(xattr_name);
165
166         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp),
167                                   sio->fsp->fsp_name->base_name);
168         if (sio->base == NULL) {
169                 DBG_DEBUG("sio->base==NULL\n");
170                 return false;
171         }
172
173         sio->fsp_name_ptr = sio->fsp->fsp_name;
174
175         return true;
176 }
177
178 static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
179                                SMB_STRUCT_STAT *sbuf)
180 {
181         int ret = -1;
182         struct stream_io *io = (struct stream_io *)
183                 VFS_FETCH_FSP_EXTENSION(handle, fsp);
184
185         if (io == NULL || !fsp_is_alternate_stream(fsp)) {
186                 return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
187         }
188
189         DBG_DEBUG("streams_xattr_fstat called for %s\n", fsp_str_dbg(io->fsp));
190
191         if (!streams_xattr_recheck(io)) {
192                 return -1;
193         }
194
195         ret = SMB_VFS_NEXT_FSTAT(handle, fsp->base_fsp, sbuf);
196         if (ret == -1) {
197                 return -1;
198         }
199
200         sbuf->st_ex_size = get_xattr_size_fsp(fsp->base_fsp,
201                                               io->xattr_name);
202         if (sbuf->st_ex_size == -1) {
203                 SET_STAT_INVALID(*sbuf);
204                 return -1;
205         }
206
207         DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size));
208
209         sbuf->st_ex_ino = hash_inode(sbuf, io->xattr_name);
210         sbuf->st_ex_mode &= ~S_IFMT;
211         sbuf->st_ex_mode &= ~S_IFDIR;
212         sbuf->st_ex_mode |= S_IFREG;
213         sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
214
215         return 0;
216 }
217
218 static int streams_xattr_stat(vfs_handle_struct *handle,
219                               struct smb_filename *smb_fname)
220 {
221         NTSTATUS status;
222         int result = -1;
223         char *xattr_name = NULL;
224         char *tmp_stream_name = NULL;
225         struct smb_filename *pathref = NULL;
226         struct files_struct *fsp = smb_fname->fsp;
227
228         if (!is_named_stream(smb_fname)) {
229                 return SMB_VFS_NEXT_STAT(handle, smb_fname);
230         }
231
232         /* Note if lp_posix_paths() is true, we can never
233          * get here as is_named_stream() is
234          * always false. So we never need worry about
235          * not following links here. */
236
237         /* Populate the stat struct with info from the base file. */
238         tmp_stream_name = smb_fname->stream_name;
239         smb_fname->stream_name = NULL;
240         result = SMB_VFS_NEXT_STAT(handle, smb_fname);
241         smb_fname->stream_name = tmp_stream_name;
242
243         if (result == -1) {
244                 return -1;
245         }
246
247         /* Derive the xattr name to lookup. */
248         status = streams_xattr_get_name(handle, talloc_tos(),
249                                         smb_fname->stream_name, &xattr_name);
250         if (!NT_STATUS_IS_OK(status)) {
251                 errno = map_errno_from_nt_status(status);
252                 return -1;
253         }
254
255         /* Augment the base file's stat information before returning. */
256         if (fsp == NULL) {
257                 status = synthetic_pathref(talloc_tos(),
258                                            handle->conn->cwd_fsp,
259                                            smb_fname->base_name,
260                                            NULL,
261                                            NULL,
262                                            smb_fname->twrp,
263                                            smb_fname->flags,
264                                            &pathref);
265                 if (!NT_STATUS_IS_OK(status)) {
266                         TALLOC_FREE(xattr_name);
267                         SET_STAT_INVALID(smb_fname->st);
268                         errno = ENOENT;
269                         return -1;
270                 }
271                 fsp = pathref->fsp;
272         } else {
273                 fsp = fsp->base_fsp;
274         }
275
276         smb_fname->st.st_ex_size = get_xattr_size_fsp(fsp,
277                                                       xattr_name);
278         if (smb_fname->st.st_ex_size == -1) {
279                 TALLOC_FREE(xattr_name);
280                 TALLOC_FREE(pathref);
281                 SET_STAT_INVALID(smb_fname->st);
282                 errno = ENOENT;
283                 return -1;
284         }
285
286         smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, xattr_name);
287         smb_fname->st.st_ex_mode &= ~S_IFMT;
288         smb_fname->st.st_ex_mode |= S_IFREG;
289         smb_fname->st.st_ex_blocks =
290             smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
291
292         TALLOC_FREE(xattr_name);
293         TALLOC_FREE(pathref);
294         return 0;
295 }
296
297 static int streams_xattr_lstat(vfs_handle_struct *handle,
298                                struct smb_filename *smb_fname)
299 {
300         if (is_named_stream(smb_fname)) {
301                 /*
302                  * There can never be EA's on a symlink.
303                  * Windows will never see a symlink, and
304                  * in SMB_FILENAME_POSIX_PATH mode we don't
305                  * allow EA's on a symlink.
306                  */
307                 SET_STAT_INVALID(smb_fname->st);
308                 errno = ENOENT;
309                 return -1;
310         }
311         return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
312 }
313
314 static int streams_xattr_openat(struct vfs_handle_struct *handle,
315                                 const struct files_struct *dirfsp,
316                                 const struct smb_filename *smb_fname,
317                                 files_struct *fsp,
318                                 const struct vfs_open_how *how)
319 {
320         NTSTATUS status;
321         struct streams_xattr_config *config = NULL;
322         struct stream_io *sio = NULL;
323         struct ea_struct ea;
324         char *xattr_name = NULL;
325         int fakefd = -1;
326         bool set_empty_xattr = false;
327         int ret;
328
329         SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
330                                 return -1);
331
332         DBG_DEBUG("called for %s with flags 0x%x\n",
333                   smb_fname_str_dbg(smb_fname),
334                   how->flags);
335
336         if (!is_named_stream(smb_fname)) {
337                 return SMB_VFS_NEXT_OPENAT(handle,
338                                            dirfsp,
339                                            smb_fname,
340                                            fsp,
341                                            how);
342         }
343
344         if (how->resolve != 0) {
345                 errno = ENOSYS;
346                 return -1;
347         }
348
349         SMB_ASSERT(fsp_is_alternate_stream(fsp));
350         SMB_ASSERT(dirfsp == NULL);
351
352         status = streams_xattr_get_name(handle, talloc_tos(),
353                                         smb_fname->stream_name, &xattr_name);
354         if (!NT_STATUS_IS_OK(status)) {
355                 errno = map_errno_from_nt_status(status);
356                 goto fail;
357         }
358
359         status = get_ea_value_fsp(talloc_tos(),
360                                   fsp->base_fsp,
361                                   xattr_name,
362                                   &ea);
363
364         DBG_DEBUG("get_ea_value_fsp returned %s\n", nt_errstr(status));
365
366         if (!NT_STATUS_IS_OK(status)) {
367                 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
368                         /*
369                          * The base file is not there. This is an error even if
370                          * we got O_CREAT, the higher levels should have created
371                          * the base file for us.
372                          */
373                         DBG_DEBUG("streams_xattr_open: base file %s not around, "
374                                   "returning ENOENT\n", smb_fname->base_name);
375                         errno = ENOENT;
376                         goto fail;
377                 }
378
379                 if (!(how->flags & O_CREAT)) {
380                         errno = ENOATTR;
381                         goto fail;
382                 }
383
384                 set_empty_xattr = true;
385         }
386
387         if (how->flags & O_TRUNC) {
388                 set_empty_xattr = true;
389         }
390
391         if (set_empty_xattr) {
392                 /*
393                  * The attribute does not exist or needs to be truncated
394                  */
395
396                 /*
397                  * Darn, xattrs need at least 1 byte
398                  */
399                 char null = '\0';
400
401                 DEBUG(10, ("creating or truncating attribute %s on file %s\n",
402                            xattr_name, smb_fname->base_name));
403
404                 ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
405                                        xattr_name,
406                                        &null, sizeof(null),
407                                        how->flags & O_EXCL ? XATTR_CREATE : 0);
408                 if (ret != 0) {
409                         goto fail;
410                 }
411         }
412
413         fakefd = vfs_fake_fd();
414
415         sio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct stream_io, NULL);
416         if (sio == NULL) {
417                 errno = ENOMEM;
418                 goto fail;
419         }
420
421         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
422                                         xattr_name);
423         if (sio->xattr_name == NULL) {
424                 errno = ENOMEM;
425                 goto fail;
426         }
427
428         /*
429          * so->base needs to be a copy of fsp->fsp_name->base_name,
430          * making it identical to streams_xattr_recheck(). If the
431          * open is changing directories, fsp->fsp_name->base_name
432          * will be the full path from the share root, whilst
433          * smb_fname will be relative to the $cwd.
434          */
435         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
436                                   fsp->fsp_name->base_name);
437         if (sio->base == NULL) {
438                 errno = ENOMEM;
439                 goto fail;
440         }
441
442         sio->fsp_name_ptr = fsp->fsp_name;
443         sio->handle = handle;
444         sio->fsp = fsp;
445
446         return fakefd;
447
448  fail:
449         if (fakefd >= 0) {
450                 vfs_fake_fd_close(fakefd);
451                 fakefd = -1;
452         }
453
454         return -1;
455 }
456
457 static int streams_xattr_close(vfs_handle_struct *handle,
458                                files_struct *fsp)
459 {
460         int ret;
461         int fd;
462
463         fd = fsp_get_pathref_fd(fsp);
464
465         DBG_DEBUG("streams_xattr_close called [%s] fd [%d]\n",
466                         smb_fname_str_dbg(fsp->fsp_name), fd);
467
468         if (!fsp_is_alternate_stream(fsp)) {
469                 return SMB_VFS_NEXT_CLOSE(handle, fsp);
470         }
471
472         ret = vfs_fake_fd_close(fd);
473         fsp_set_fd(fsp, -1);
474
475         return ret;
476 }
477
478 static int streams_xattr_unlinkat(vfs_handle_struct *handle,
479                         struct files_struct *dirfsp,
480                         const struct smb_filename *smb_fname,
481                         int flags)
482 {
483         NTSTATUS status;
484         int ret = -1;
485         char *xattr_name = NULL;
486         struct smb_filename *pathref = NULL;
487         struct files_struct *fsp = smb_fname->fsp;
488
489         if (!is_named_stream(smb_fname)) {
490                 return SMB_VFS_NEXT_UNLINKAT(handle,
491                                         dirfsp,
492                                         smb_fname,
493                                         flags);
494         }
495
496         /* A stream can never be rmdir'ed */
497         SMB_ASSERT((flags & AT_REMOVEDIR) == 0);
498
499         status = streams_xattr_get_name(handle, talloc_tos(),
500                                         smb_fname->stream_name, &xattr_name);
501         if (!NT_STATUS_IS_OK(status)) {
502                 errno = map_errno_from_nt_status(status);
503                 goto fail;
504         }
505
506         if (fsp == NULL) {
507                 status = synthetic_pathref(talloc_tos(),
508                                         handle->conn->cwd_fsp,
509                                         smb_fname->base_name,
510                                         NULL,
511                                         NULL,
512                                         smb_fname->twrp,
513                                         smb_fname->flags,
514                                         &pathref);
515                 if (!NT_STATUS_IS_OK(status)) {
516                         errno = ENOENT;
517                         goto fail;
518                 }
519                 fsp = pathref->fsp;
520         } else {
521                 SMB_ASSERT(fsp_is_alternate_stream(smb_fname->fsp));
522                 fsp = fsp->base_fsp;
523         }
524
525         ret = SMB_VFS_FREMOVEXATTR(fsp, xattr_name);
526
527         if ((ret == -1) && (errno == ENOATTR)) {
528                 errno = ENOENT;
529                 goto fail;
530         }
531
532         ret = 0;
533
534  fail:
535         TALLOC_FREE(xattr_name);
536         TALLOC_FREE(pathref);
537         return ret;
538 }
539
540 static int streams_xattr_renameat(vfs_handle_struct *handle,
541                                 files_struct *srcfsp,
542                                 const struct smb_filename *smb_fname_src,
543                                 files_struct *dstfsp,
544                                 const struct smb_filename *smb_fname_dst)
545 {
546         NTSTATUS status;
547         int ret = -1;
548         char *src_xattr_name = NULL;
549         char *dst_xattr_name = NULL;
550         bool src_is_stream, dst_is_stream;
551         ssize_t oret;
552         ssize_t nret;
553         struct ea_struct ea;
554         struct smb_filename *pathref_src = NULL;
555         struct smb_filename *pathref_dst = NULL;
556         struct smb_filename *full_src = NULL;
557         struct smb_filename *full_dst = NULL;
558
559         src_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
560         dst_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
561
562         if (!src_is_stream && !dst_is_stream) {
563                 return SMB_VFS_NEXT_RENAMEAT(handle,
564                                         srcfsp,
565                                         smb_fname_src,
566                                         dstfsp,
567                                         smb_fname_dst);
568         }
569
570         /* For now don't allow renames from or to the default stream. */
571         if (is_ntfs_default_stream_smb_fname(smb_fname_src) ||
572             is_ntfs_default_stream_smb_fname(smb_fname_dst)) {
573                 errno = ENOSYS;
574                 goto done;
575         }
576
577         /* Don't rename if the streams are identical. */
578         if (strcasecmp_m(smb_fname_src->stream_name,
579                        smb_fname_dst->stream_name) == 0) {
580                 goto done;
581         }
582
583         /* Get the xattr names. */
584         status = streams_xattr_get_name(handle, talloc_tos(),
585                                         smb_fname_src->stream_name,
586                                         &src_xattr_name);
587         if (!NT_STATUS_IS_OK(status)) {
588                 errno = map_errno_from_nt_status(status);
589                 goto fail;
590         }
591         status = streams_xattr_get_name(handle, talloc_tos(),
592                                         smb_fname_dst->stream_name,
593                                         &dst_xattr_name);
594         if (!NT_STATUS_IS_OK(status)) {
595                 errno = map_errno_from_nt_status(status);
596                 goto fail;
597         }
598
599         full_src = full_path_from_dirfsp_atname(talloc_tos(),
600                                                 srcfsp,
601                                                 smb_fname_src);
602         if (full_src == NULL) {
603                 errno = ENOMEM;
604                 goto fail;
605         }
606         full_dst = full_path_from_dirfsp_atname(talloc_tos(),
607                                                 dstfsp,
608                                                 smb_fname_dst);
609         if (full_dst == NULL) {
610                 errno = ENOMEM;
611                 goto fail;
612         }
613
614         /* Get a pathref for full_src (base file, no stream name). */
615         status = synthetic_pathref(talloc_tos(),
616                                 handle->conn->cwd_fsp,
617                                 full_src->base_name,
618                                 NULL,
619                                 NULL,
620                                 full_src->twrp,
621                                 full_src->flags,
622                                 &pathref_src);
623         if (!NT_STATUS_IS_OK(status)) {
624                 errno = ENOENT;
625                 goto fail;
626         }
627
628         /* Read the old stream from the base file fsp. */
629         status = get_ea_value_fsp(talloc_tos(),
630                                   pathref_src->fsp,
631                                   src_xattr_name,
632                                   &ea);
633         if (!NT_STATUS_IS_OK(status)) {
634                 errno = map_errno_from_nt_status(status);
635                 goto fail;
636         }
637
638         /* Get a pathref for full_dst (base file, no stream name). */
639         status = synthetic_pathref(talloc_tos(),
640                                 handle->conn->cwd_fsp,
641                                 full_dst->base_name,
642                                 NULL,
643                                 NULL,
644                                 full_dst->twrp,
645                                 full_dst->flags,
646                                 &pathref_dst);
647         if (!NT_STATUS_IS_OK(status)) {
648                 errno = ENOENT;
649                 goto fail;
650         }
651
652         /* (Over)write the new stream on the base file fsp. */
653         nret = SMB_VFS_FSETXATTR(
654                         pathref_dst->fsp,
655                         dst_xattr_name,
656                         ea.value.data,
657                         ea.value.length,
658                         0);
659         if (nret < 0) {
660                 if (errno == ENOATTR) {
661                         errno = ENOENT;
662                 }
663                 goto fail;
664         }
665
666         /*
667          * Remove the old stream from the base file fsp.
668          */
669         oret = SMB_VFS_FREMOVEXATTR(pathref_src->fsp,
670                                     src_xattr_name);
671         if (oret < 0) {
672                 if (errno == ENOATTR) {
673                         errno = ENOENT;
674                 }
675                 goto fail;
676         }
677
678  done:
679         errno = 0;
680         ret = 0;
681  fail:
682         TALLOC_FREE(pathref_src);
683         TALLOC_FREE(pathref_dst);
684         TALLOC_FREE(full_src);
685         TALLOC_FREE(full_dst);
686         TALLOC_FREE(src_xattr_name);
687         TALLOC_FREE(dst_xattr_name);
688         return ret;
689 }
690
691 static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle,
692                                 files_struct *fsp,
693                                 const struct smb_filename *smb_fname,
694                                 bool (*fn)(struct ea_struct *ea,
695                                         void *private_data),
696                                 void *private_data)
697 {
698         NTSTATUS status;
699         char **names;
700         size_t i, num_names;
701         struct streams_xattr_config *config;
702
703         SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
704                                 return NT_STATUS_UNSUCCESSFUL);
705
706         status = get_ea_names_from_fsp(talloc_tos(),
707                                 smb_fname->fsp,
708                                 &names,
709                                 &num_names);
710         if (!NT_STATUS_IS_OK(status)) {
711                 return status;
712         }
713
714         for (i=0; i<num_names; i++) {
715                 struct ea_struct ea;
716
717                 /*
718                  * We want to check with samba_private_attr_name()
719                  * whether the xattr name is a private one,
720                  * unfortunately it flags xattrs that begin with the
721                  * default streams prefix as private.
722                  *
723                  * By only calling samba_private_attr_name() in case
724                  * the xattr does NOT begin with the default prefix,
725                  * we know that if it returns 'true' it definitely one
726                  * of our internal xattr like "user.DOSATTRIB".
727                  */
728                 if (strncasecmp_m(names[i], SAMBA_XATTR_DOSSTREAM_PREFIX,
729                                   strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) != 0) {
730                         if (samba_private_attr_name(names[i])) {
731                                 continue;
732                         }
733                 }
734
735                 if (strncmp(names[i], config->prefix,
736                             config->prefix_len) != 0) {
737                         continue;
738                 }
739
740                 status = get_ea_value_fsp(names,
741                                           smb_fname->fsp,
742                                           names[i],
743                                           &ea);
744                 if (!NT_STATUS_IS_OK(status)) {
745                         DEBUG(10, ("Could not get ea %s for file %s: %s\n",
746                                 names[i],
747                                 smb_fname->base_name,
748                                 nt_errstr(status)));
749                         continue;
750                 }
751
752                 ea.name = talloc_asprintf(
753                         ea.value.data, ":%s%s",
754                         names[i] + config->prefix_len,
755                         config->store_stream_type ? "" : ":$DATA");
756                 if (ea.name == NULL) {
757                         DEBUG(0, ("talloc failed\n"));
758                         continue;
759                 }
760
761                 if (!fn(&ea, private_data)) {
762                         TALLOC_FREE(ea.value.data);
763                         return NT_STATUS_OK;
764                 }
765
766                 TALLOC_FREE(ea.value.data);
767         }
768
769         TALLOC_FREE(names);
770         return NT_STATUS_OK;
771 }
772
773 static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
774                            struct stream_struct **streams,
775                            const char *name, off_t size,
776                            off_t alloc_size)
777 {
778         struct stream_struct *tmp;
779
780         tmp = talloc_realloc(mem_ctx, *streams, struct stream_struct,
781                                    (*num_streams)+1);
782         if (tmp == NULL) {
783                 return false;
784         }
785
786         tmp[*num_streams].name = talloc_strdup(tmp, name);
787         if (tmp[*num_streams].name == NULL) {
788                 return false;
789         }
790
791         tmp[*num_streams].size = size;
792         tmp[*num_streams].alloc_size = alloc_size;
793
794         *streams = tmp;
795         *num_streams += 1;
796         return true;
797 }
798
799 struct streaminfo_state {
800         TALLOC_CTX *mem_ctx;
801         vfs_handle_struct *handle;
802         unsigned int num_streams;
803         struct stream_struct *streams;
804         NTSTATUS status;
805 };
806
807 static bool collect_one_stream(struct ea_struct *ea, void *private_data)
808 {
809         struct streaminfo_state *state =
810                 (struct streaminfo_state *)private_data;
811
812         if (!add_one_stream(state->mem_ctx,
813                             &state->num_streams, &state->streams,
814                             ea->name, ea->value.length-1,
815                             smb_roundup(state->handle->conn,
816                                         ea->value.length-1))) {
817                 state->status = NT_STATUS_NO_MEMORY;
818                 return false;
819         }
820
821         return true;
822 }
823
824 static NTSTATUS streams_xattr_fstreaminfo(vfs_handle_struct *handle,
825                                          struct files_struct *fsp,
826                                          TALLOC_CTX *mem_ctx,
827                                          unsigned int *pnum_streams,
828                                          struct stream_struct **pstreams)
829 {
830         NTSTATUS status;
831         struct streaminfo_state state;
832
833         state.streams = *pstreams;
834         state.num_streams = *pnum_streams;
835         state.mem_ctx = mem_ctx;
836         state.handle = handle;
837         state.status = NT_STATUS_OK;
838
839         status = walk_xattr_streams(handle,
840                                     fsp,
841                                     fsp->fsp_name,
842                                     collect_one_stream,
843                                     &state);
844
845         if (!NT_STATUS_IS_OK(status)) {
846                 TALLOC_FREE(state.streams);
847                 return status;
848         }
849
850         if (!NT_STATUS_IS_OK(state.status)) {
851                 TALLOC_FREE(state.streams);
852                 return state.status;
853         }
854
855         *pnum_streams = state.num_streams;
856         *pstreams = state.streams;
857
858         return SMB_VFS_NEXT_FSTREAMINFO(handle,
859                         fsp,
860                         mem_ctx,
861                         pnum_streams,
862                         pstreams);
863 }
864
865 static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle,
866                         enum timestamp_set_resolution *p_ts_res)
867 {
868         return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS;
869 }
870
871 static int streams_xattr_connect(vfs_handle_struct *handle,
872                                  const char *service, const char *user)
873 {
874         struct streams_xattr_config *config;
875         const char *default_prefix = SAMBA_XATTR_DOSSTREAM_PREFIX;
876         const char *prefix;
877         int rc;
878
879         rc = SMB_VFS_NEXT_CONNECT(handle, service, user);
880         if (rc != 0) {
881                 return rc;
882         }
883
884         config = talloc_zero(handle->conn, struct streams_xattr_config);
885         if (config == NULL) {
886                 DEBUG(1, ("talloc_zero() failed\n"));
887                 errno = ENOMEM;
888                 return -1;
889         }
890
891         prefix = lp_parm_const_string(SNUM(handle->conn),
892                                       "streams_xattr", "prefix",
893                                       default_prefix);
894         config->prefix = talloc_strdup(config, prefix);
895         if (config->prefix == NULL) {
896                 DEBUG(1, ("talloc_strdup() failed\n"));
897                 errno = ENOMEM;
898                 return -1;
899         }
900         config->prefix_len = strlen(config->prefix);
901         DEBUG(10, ("streams_xattr using stream prefix: %s\n", config->prefix));
902
903         config->store_stream_type = lp_parm_bool(SNUM(handle->conn),
904                                                  "streams_xattr",
905                                                  "store_stream_type",
906                                                  true);
907
908         SMB_VFS_HANDLE_SET_DATA(handle, config,
909                                 NULL, struct stream_xattr_config,
910                                 return -1);
911
912         return 0;
913 }
914
915 static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
916                                     files_struct *fsp, const void *data,
917                                     size_t n, off_t offset)
918 {
919         struct stream_io *sio =
920                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
921         struct ea_struct ea;
922         NTSTATUS status;
923         int ret;
924
925         DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n));
926
927         if (sio == NULL) {
928                 return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
929         }
930
931         if (!streams_xattr_recheck(sio)) {
932                 return -1;
933         }
934
935         if ((offset + n) >= lp_smbd_max_xattr_size(SNUM(handle->conn))) {
936                 /*
937                  * Requested write is beyond what can be read based on
938                  * samba configuration.
939                  * ReFS returns STATUS_FILESYSTEM_LIMITATION, which causes
940                  * entire file to be skipped by File Explorer. VFAT returns
941                  * NT_STATUS_OBJECT_NAME_COLLISION causes user to be prompted
942                  * to skip writing metadata, but copy data.
943                  */
944                 DBG_ERR("Write to xattr [%s] on file [%s] exceeds maximum "
945                         "supported extended attribute size. "
946                         "Depending on filesystem type and operating system "
947                         "(OS) specifics, this value may be increased using "
948                         "the value of the parameter: "
949                         "smbd max xattr size = <bytes>. Consult OS and "
950                         "filesystem manpages prior to increasing this limit.\n",
951                         sio->xattr_name, sio->base);
952                 errno = EOVERFLOW;
953                 return -1;
954         }
955
956         status = get_ea_value_fsp(talloc_tos(),
957                                   fsp->base_fsp,
958                                   sio->xattr_name,
959                                   &ea);
960         if (!NT_STATUS_IS_OK(status)) {
961                 return -1;
962         }
963
964         if ((offset + n) > ea.value.length-1) {
965                 uint8_t *tmp;
966
967                 tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8_t,
968                                            offset + n + 1);
969
970                 if (tmp == NULL) {
971                         TALLOC_FREE(ea.value.data);
972                         errno = ENOMEM;
973                         return -1;
974                 }
975                 ea.value.data = tmp;
976                 ea.value.length = offset + n + 1;
977                 ea.value.data[offset+n] = 0;
978         }
979
980         memcpy(ea.value.data + offset, data, n);
981
982         ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
983                                 sio->xattr_name,
984                                 ea.value.data,
985                                 ea.value.length,
986                                 0);
987         TALLOC_FREE(ea.value.data);
988
989         if (ret == -1) {
990                 return -1;
991         }
992
993         return n;
994 }
995
996 static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
997                                    files_struct *fsp, void *data,
998                                    size_t n, off_t offset)
999 {
1000         struct stream_io *sio =
1001                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1002         struct ea_struct ea;
1003         NTSTATUS status;
1004         size_t length, overlap;
1005
1006         DEBUG(10, ("streams_xattr_pread: offset=%d, size=%d\n",
1007                    (int)offset, (int)n));
1008
1009         if (sio == NULL) {
1010                 return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
1011         }
1012
1013         if (!streams_xattr_recheck(sio)) {
1014                 return -1;
1015         }
1016
1017         status = get_ea_value_fsp(talloc_tos(),
1018                                   fsp->base_fsp,
1019                                   sio->xattr_name,
1020                                   &ea);
1021         if (!NT_STATUS_IS_OK(status)) {
1022                 return -1;
1023         }
1024
1025         length = ea.value.length-1;
1026
1027         DBG_DEBUG("get_ea_value_fsp returned %d bytes\n",
1028                    (int)length);
1029
1030         /* Attempt to read past EOF. */
1031         if (length <= offset) {
1032                 return 0;
1033         }
1034
1035         overlap = (offset + n) > length ? (length - offset) : n;
1036         memcpy(data, ea.value.data + offset, overlap);
1037
1038         TALLOC_FREE(ea.value.data);
1039         return overlap;
1040 }
1041
1042 struct streams_xattr_pread_state {
1043         ssize_t nread;
1044         struct vfs_aio_state vfs_aio_state;
1045 };
1046
1047 static void streams_xattr_pread_done(struct tevent_req *subreq);
1048
1049 static struct tevent_req *streams_xattr_pread_send(
1050         struct vfs_handle_struct *handle,
1051         TALLOC_CTX *mem_ctx,
1052         struct tevent_context *ev,
1053         struct files_struct *fsp,
1054         void *data,
1055         size_t n, off_t offset)
1056 {
1057         struct tevent_req *req = NULL;
1058         struct tevent_req *subreq = NULL;
1059         struct streams_xattr_pread_state *state = NULL;
1060         struct stream_io *sio =
1061                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1062
1063         req = tevent_req_create(mem_ctx, &state,
1064                                 struct streams_xattr_pread_state);
1065         if (req == NULL) {
1066                 return NULL;
1067         }
1068
1069         if (sio == NULL) {
1070                 subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp,
1071                                                  data, n, offset);
1072                 if (tevent_req_nomem(req, subreq)) {
1073                         return tevent_req_post(req, ev);
1074                 }
1075                 tevent_req_set_callback(subreq, streams_xattr_pread_done, req);
1076                 return req;
1077         }
1078
1079         state->nread = SMB_VFS_PREAD(fsp, data, n, offset);
1080         if (state->nread != n) {
1081                 if (state->nread != -1) {
1082                         errno = EIO;
1083                 }
1084                 tevent_req_error(req, errno);
1085                 return tevent_req_post(req, ev);
1086         }
1087
1088         tevent_req_done(req);
1089         return tevent_req_post(req, ev);
1090 }
1091
1092 static void streams_xattr_pread_done(struct tevent_req *subreq)
1093 {
1094         struct tevent_req *req = tevent_req_callback_data(
1095                 subreq, struct tevent_req);
1096         struct streams_xattr_pread_state *state = tevent_req_data(
1097                 req, struct streams_xattr_pread_state);
1098
1099         state->nread = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
1100         TALLOC_FREE(subreq);
1101
1102         if (tevent_req_error(req, state->vfs_aio_state.error)) {
1103                 return;
1104         }
1105         tevent_req_done(req);
1106 }
1107
1108 static ssize_t streams_xattr_pread_recv(struct tevent_req *req,
1109                                         struct vfs_aio_state *vfs_aio_state)
1110 {
1111         struct streams_xattr_pread_state *state = tevent_req_data(
1112                 req, struct streams_xattr_pread_state);
1113
1114         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1115                 return -1;
1116         }
1117
1118         *vfs_aio_state = state->vfs_aio_state;
1119         return state->nread;
1120 }
1121
1122 struct streams_xattr_pwrite_state {
1123         ssize_t nwritten;
1124         struct vfs_aio_state vfs_aio_state;
1125 };
1126
1127 static void streams_xattr_pwrite_done(struct tevent_req *subreq);
1128
1129 static struct tevent_req *streams_xattr_pwrite_send(
1130         struct vfs_handle_struct *handle,
1131         TALLOC_CTX *mem_ctx,
1132         struct tevent_context *ev,
1133         struct files_struct *fsp,
1134         const void *data,
1135         size_t n, off_t offset)
1136 {
1137         struct tevent_req *req = NULL;
1138         struct tevent_req *subreq = NULL;
1139         struct streams_xattr_pwrite_state *state = NULL;
1140         struct stream_io *sio =
1141                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1142
1143         req = tevent_req_create(mem_ctx, &state,
1144                                 struct streams_xattr_pwrite_state);
1145         if (req == NULL) {
1146                 return NULL;
1147         }
1148
1149         if (sio == NULL) {
1150                 subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp,
1151                                                   data, n, offset);
1152                 if (tevent_req_nomem(req, subreq)) {
1153                         return tevent_req_post(req, ev);
1154                 }
1155                 tevent_req_set_callback(subreq, streams_xattr_pwrite_done, req);
1156                 return req;
1157         }
1158
1159         state->nwritten = SMB_VFS_PWRITE(fsp, data, n, offset);
1160         if (state->nwritten != n) {
1161                 if (state->nwritten != -1) {
1162                         errno = EIO;
1163                 }
1164                 tevent_req_error(req, errno);
1165                 return tevent_req_post(req, ev);
1166         }
1167
1168         tevent_req_done(req);
1169         return tevent_req_post(req, ev);
1170 }
1171
1172 static void streams_xattr_pwrite_done(struct tevent_req *subreq)
1173 {
1174         struct tevent_req *req = tevent_req_callback_data(
1175                 subreq, struct tevent_req);
1176         struct streams_xattr_pwrite_state *state = tevent_req_data(
1177                 req, struct streams_xattr_pwrite_state);
1178
1179         state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
1180         TALLOC_FREE(subreq);
1181
1182         if (tevent_req_error(req, state->vfs_aio_state.error)) {
1183                 return;
1184         }
1185         tevent_req_done(req);
1186 }
1187
1188 static ssize_t streams_xattr_pwrite_recv(struct tevent_req *req,
1189                                          struct vfs_aio_state *vfs_aio_state)
1190 {
1191         struct streams_xattr_pwrite_state *state = tevent_req_data(
1192                 req, struct streams_xattr_pwrite_state);
1193
1194         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1195                 return -1;
1196         }
1197
1198         *vfs_aio_state = state->vfs_aio_state;
1199         return state->nwritten;
1200 }
1201
1202 static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
1203                                         struct files_struct *fsp,
1204                                         off_t offset)
1205 {
1206         int ret;
1207         uint8_t *tmp;
1208         struct ea_struct ea;
1209         NTSTATUS status;
1210         struct stream_io *sio =
1211                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1212
1213         DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
1214                    fsp_str_dbg(fsp), (double)offset));
1215
1216         if (sio == NULL) {
1217                 return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
1218         }
1219
1220         if (!streams_xattr_recheck(sio)) {
1221                 return -1;
1222         }
1223
1224         status = get_ea_value_fsp(talloc_tos(),
1225                                   fsp->base_fsp,
1226                                   sio->xattr_name,
1227                                   &ea);
1228         if (!NT_STATUS_IS_OK(status)) {
1229                 return -1;
1230         }
1231
1232         tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8_t,
1233                                    offset + 1);
1234
1235         if (tmp == NULL) {
1236                 TALLOC_FREE(ea.value.data);
1237                 errno = ENOMEM;
1238                 return -1;
1239         }
1240
1241         /* Did we expand ? */
1242         if (ea.value.length < offset + 1) {
1243                 memset(&tmp[ea.value.length], '\0',
1244                         offset + 1 - ea.value.length);
1245         }
1246
1247         ea.value.data = tmp;
1248         ea.value.length = offset + 1;
1249         ea.value.data[offset] = 0;
1250
1251         ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
1252                                 sio->xattr_name,
1253                                 ea.value.data,
1254                                 ea.value.length,
1255                                 0);
1256
1257         TALLOC_FREE(ea.value.data);
1258
1259         if (ret == -1) {
1260                 return -1;
1261         }
1262
1263         return 0;
1264 }
1265
1266 static int streams_xattr_fallocate(struct vfs_handle_struct *handle,
1267                                         struct files_struct *fsp,
1268                                         uint32_t mode,
1269                                         off_t offset,
1270                                         off_t len)
1271 {
1272         struct stream_io *sio =
1273                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1274
1275         DEBUG(10, ("streams_xattr_fallocate called for file %s offset %.0f"
1276                 "len = %.0f\n",
1277                 fsp_str_dbg(fsp), (double)offset, (double)len));
1278
1279         if (sio == NULL) {
1280                 return SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1281         }
1282
1283         if (!streams_xattr_recheck(sio)) {
1284                 return -1;
1285         }
1286
1287         /* Let the pwrite code path handle it. */
1288         errno = ENOSYS;
1289         return -1;
1290 }
1291
1292 static int streams_xattr_fchown(vfs_handle_struct *handle, files_struct *fsp,
1293                                 uid_t uid, gid_t gid)
1294 {
1295         struct stream_io *sio =
1296                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1297
1298         if (sio == NULL) {
1299                 return SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1300         }
1301
1302         return 0;
1303 }
1304
1305 static int streams_xattr_fchmod(vfs_handle_struct *handle,
1306                                 files_struct *fsp,
1307                                 mode_t mode)
1308 {
1309         struct stream_io *sio =
1310                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1311
1312         if (sio == NULL) {
1313                 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1314         }
1315
1316         return 0;
1317 }
1318
1319 static ssize_t streams_xattr_fgetxattr(struct vfs_handle_struct *handle,
1320                                        struct files_struct *fsp,
1321                                        const char *name,
1322                                        void *value,
1323                                        size_t size)
1324 {
1325         struct stream_io *sio =
1326                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1327
1328         if (sio == NULL) {
1329                 return SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
1330         }
1331
1332         errno = ENOTSUP;
1333         return -1;
1334 }
1335
1336 static ssize_t streams_xattr_flistxattr(struct vfs_handle_struct *handle,
1337                                         struct files_struct *fsp,
1338                                         char *list,
1339                                         size_t size)
1340 {
1341         struct stream_io *sio =
1342                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1343
1344         if (sio == NULL) {
1345                 return SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
1346         }
1347
1348         errno = ENOTSUP;
1349         return -1;
1350 }
1351
1352 static int streams_xattr_fremovexattr(struct vfs_handle_struct *handle,
1353                                       struct files_struct *fsp,
1354                                       const char *name)
1355 {
1356         struct stream_io *sio =
1357                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1358
1359         if (sio == NULL) {
1360                 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
1361         }
1362
1363         errno = ENOTSUP;
1364         return -1;
1365 }
1366
1367 static int streams_xattr_fsetxattr(struct vfs_handle_struct *handle,
1368                                    struct files_struct *fsp,
1369                                    const char *name,
1370                                    const void *value,
1371                                    size_t size,
1372                                    int flags)
1373 {
1374         struct stream_io *sio =
1375                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1376
1377         if (sio == NULL) {
1378                 return SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value,
1379                                               size, flags);
1380         }
1381
1382         errno = ENOTSUP;
1383         return -1;
1384 }
1385
1386 struct streams_xattr_fsync_state {
1387         int ret;
1388         struct vfs_aio_state vfs_aio_state;
1389 };
1390
1391 static void streams_xattr_fsync_done(struct tevent_req *subreq);
1392
1393 static struct tevent_req *streams_xattr_fsync_send(
1394         struct vfs_handle_struct *handle,
1395         TALLOC_CTX *mem_ctx,
1396         struct tevent_context *ev,
1397         struct files_struct *fsp)
1398 {
1399         struct tevent_req *req = NULL;
1400         struct tevent_req *subreq = NULL;
1401         struct streams_xattr_fsync_state *state = NULL;
1402         struct stream_io *sio =
1403                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1404
1405         req = tevent_req_create(mem_ctx, &state,
1406                                 struct streams_xattr_fsync_state);
1407         if (req == NULL) {
1408                 return NULL;
1409         }
1410
1411         if (sio == NULL) {
1412                 subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
1413                 if (tevent_req_nomem(req, subreq)) {
1414                         return tevent_req_post(req, ev);
1415                 }
1416                 tevent_req_set_callback(subreq, streams_xattr_fsync_done, req);
1417                 return req;
1418         }
1419
1420         /*
1421          * There's no pathname based sync variant and we don't have access to
1422          * the basefile handle, so we can't do anything here.
1423          */
1424
1425         tevent_req_done(req);
1426         return tevent_req_post(req, ev);
1427 }
1428
1429 static void streams_xattr_fsync_done(struct tevent_req *subreq)
1430 {
1431         struct tevent_req *req = tevent_req_callback_data(
1432                 subreq, struct tevent_req);
1433         struct streams_xattr_fsync_state *state = tevent_req_data(
1434                 req, struct streams_xattr_fsync_state);
1435
1436         state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
1437         TALLOC_FREE(subreq);
1438         if (state->ret != 0) {
1439                 tevent_req_error(req, errno);
1440                 return;
1441         }
1442
1443         tevent_req_done(req);
1444 }
1445
1446 static int streams_xattr_fsync_recv(struct tevent_req *req,
1447                                     struct vfs_aio_state *vfs_aio_state)
1448 {
1449         struct streams_xattr_fsync_state *state = tevent_req_data(
1450                 req, struct streams_xattr_fsync_state);
1451
1452         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1453                 return -1;
1454         }
1455
1456         *vfs_aio_state = state->vfs_aio_state;
1457         return state->ret;
1458 }
1459
1460 static bool streams_xattr_lock(vfs_handle_struct *handle,
1461                                files_struct *fsp,
1462                                int op,
1463                                off_t offset,
1464                                off_t count,
1465                                int type)
1466 {
1467         struct stream_io *sio =
1468                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1469
1470         if (sio == NULL) {
1471                 return SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
1472         }
1473
1474         return true;
1475 }
1476
1477 static bool streams_xattr_getlock(vfs_handle_struct *handle,
1478                                   files_struct *fsp,
1479                                   off_t *poffset,
1480                                   off_t *pcount,
1481                                   int *ptype,
1482                                   pid_t *ppid)
1483 {
1484         struct stream_io *sio =
1485                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1486
1487         if (sio == NULL) {
1488                 return SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset,
1489                                             pcount, ptype, ppid);
1490         }
1491
1492         errno = ENOTSUP;
1493         return false;
1494 }
1495
1496 static int streams_xattr_filesystem_sharemode(vfs_handle_struct *handle,
1497                                               files_struct *fsp,
1498                                               uint32_t share_access,
1499                                               uint32_t access_mask)
1500 {
1501         struct stream_io *sio =
1502                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1503
1504         if (sio == NULL) {
1505                 return SMB_VFS_NEXT_FILESYSTEM_SHAREMODE(handle,
1506                                                          fsp,
1507                                                          share_access,
1508                                                          access_mask);
1509         }
1510
1511         return 0;
1512 }
1513
1514 static int streams_xattr_linux_setlease(vfs_handle_struct *handle,
1515                                         files_struct *fsp,
1516                                         int leasetype)
1517 {
1518         struct stream_io *sio =
1519                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1520
1521         if (sio == NULL) {
1522                 return SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
1523         }
1524
1525         return 0;
1526 }
1527
1528 static bool streams_xattr_strict_lock_check(struct vfs_handle_struct *handle,
1529                                             files_struct *fsp,
1530                                             struct lock_struct *plock)
1531 {
1532         struct stream_io *sio =
1533                 (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
1534
1535         if (sio == NULL) {
1536                 return SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock);
1537         }
1538
1539         return true;
1540 }
1541
1542 static struct vfs_fn_pointers vfs_streams_xattr_fns = {
1543         .fs_capabilities_fn = streams_xattr_fs_capabilities,
1544         .connect_fn = streams_xattr_connect,
1545         .openat_fn = streams_xattr_openat,
1546         .close_fn = streams_xattr_close,
1547         .stat_fn = streams_xattr_stat,
1548         .fstat_fn = streams_xattr_fstat,
1549         .lstat_fn = streams_xattr_lstat,
1550         .pread_fn = streams_xattr_pread,
1551         .pwrite_fn = streams_xattr_pwrite,
1552         .pread_send_fn = streams_xattr_pread_send,
1553         .pread_recv_fn = streams_xattr_pread_recv,
1554         .pwrite_send_fn = streams_xattr_pwrite_send,
1555         .pwrite_recv_fn = streams_xattr_pwrite_recv,
1556         .unlinkat_fn = streams_xattr_unlinkat,
1557         .renameat_fn = streams_xattr_renameat,
1558         .ftruncate_fn = streams_xattr_ftruncate,
1559         .fallocate_fn = streams_xattr_fallocate,
1560         .fstreaminfo_fn = streams_xattr_fstreaminfo,
1561
1562         .fsync_send_fn = streams_xattr_fsync_send,
1563         .fsync_recv_fn = streams_xattr_fsync_recv,
1564
1565         .lock_fn = streams_xattr_lock,
1566         .getlock_fn = streams_xattr_getlock,
1567         .filesystem_sharemode_fn = streams_xattr_filesystem_sharemode,
1568         .linux_setlease_fn = streams_xattr_linux_setlease,
1569         .strict_lock_check_fn = streams_xattr_strict_lock_check,
1570
1571         .fchown_fn = streams_xattr_fchown,
1572         .fchmod_fn = streams_xattr_fchmod,
1573
1574         .fgetxattr_fn = streams_xattr_fgetxattr,
1575         .flistxattr_fn = streams_xattr_flistxattr,
1576         .fremovexattr_fn = streams_xattr_fremovexattr,
1577         .fsetxattr_fn = streams_xattr_fsetxattr,
1578 };
1579
1580 static_decl_vfs;
1581 NTSTATUS vfs_streams_xattr_init(TALLOC_CTX *ctx)
1582 {
1583         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "streams_xattr",
1584                                 &vfs_streams_xattr_fns);
1585 }