LCOV - code coverage report
Current view: top level - source3/modules - vfs_streams_xattr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 465 661 70.3 %
Date: 2024-02-28 12:06:22 Functions: 41 43 95.3 %

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

Generated by: LCOV version 1.14