s3-vfs: Use the system. namespace for fake ACLs
[kai/samba.git] / source3 / modules / vfs_streams_xattr.c
index ae8af47ab732cf3f0807039d7afaab1fd4accd3d..dd1135d77ccbb82a4f23207710fbd455523431a6 100644 (file)
@@ -22,6 +22,9 @@
  */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "system/filesys.h"
+#include "../lib/crypto/md5.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -49,9 +52,9 @@ static SMB_INO_T stream_inode(const SMB_STRUCT_STAT *sbuf, const char *sname)
        SMB_ASSERT(upper_sname != NULL);
 
         MD5Init(&ctx);
-        MD5Update(&ctx, (unsigned char *)&(sbuf->st_ex_dev),
+        MD5Update(&ctx, (const unsigned char *)&(sbuf->st_ex_dev),
                  sizeof(sbuf->st_ex_dev));
-        MD5Update(&ctx, (unsigned char *)&(sbuf->st_ex_ino),
+        MD5Update(&ctx, (const unsigned char *)&(sbuf->st_ex_ino),
                  sizeof(sbuf->st_ex_ino));
         MD5Update(&ctx, (unsigned char *)upper_sname,
                  talloc_get_size(upper_sname)-1);
@@ -116,7 +119,9 @@ static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx,
                }
        } else {
                /* Normalize the stream type to upercase. */
-               strupper_m(strrchr_m(*xattr_name, ':') + 1);
+               if (!strupper_m(strrchr_m(*xattr_name, ':') + 1)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
        }
 
        DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
@@ -237,7 +242,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
        sbuf->st_ex_ino = stream_inode(sbuf, io->xattr_name);
        sbuf->st_ex_mode &= ~S_IFMT;
         sbuf->st_ex_mode |= S_IFREG;
-        sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1;
+        sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
 
        return 0;
 }
@@ -253,6 +258,11 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
                return SMB_VFS_NEXT_STAT(handle, smb_fname);
        }
 
+       /* Note if lp_posix_paths() is true, we can never
+        * get here as is_ntfs_stream_smb_fname() is
+        * always false. So we never need worry about
+        * not following links here. */
+
        /* If the default stream is requested, just stat the base file. */
        if (is_ntfs_default_stream_smb_fname(smb_fname)) {
                return streams_xattr_stat_base(handle, smb_fname, true);
@@ -285,7 +295,7 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
        smb_fname->st.st_ex_mode &= ~S_IFMT;
         smb_fname->st.st_ex_mode |= S_IFREG;
         smb_fname->st.st_ex_blocks =
-           smb_fname->st.st_ex_size % STAT_ST_BLOCKSIZE + 1;
+           smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
 
        result = 0;
  fail:
@@ -304,7 +314,7 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
                return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        }
 
-               /* If the default stream is requested, just stat the base file. */
+       /* If the default stream is requested, just stat the base file. */
        if (is_ntfs_default_stream_smb_fname(smb_fname)) {
                return streams_xattr_stat_base(handle, smb_fname, false);
        }
@@ -336,7 +346,7 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
        smb_fname->st.st_ex_mode &= ~S_IFMT;
         smb_fname->st.st_ex_mode |= S_IFREG;
         smb_fname->st.st_ex_blocks =
-           smb_fname->st.st_ex_size % STAT_ST_BLOCKSIZE + 1;
+           smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
 
        result = 0;
 
@@ -606,7 +616,7 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
        }
 
        /* Don't rename if the streams are identical. */
-       if (StrCaseCmp(smb_fname_src->stream_name,
+       if (strcasecmp_m(smb_fname_src->stream_name,
                       smb_fname_dst->stream_name) == 0) {
                goto done;
        }
@@ -718,12 +728,12 @@ static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
 
 static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
                           struct stream_struct **streams,
-                          const char *name, SMB_OFF_T size,
-                          SMB_OFF_T alloc_size)
+                          const char *name, off_t size,
+                          off_t alloc_size)
 {
        struct stream_struct *tmp;
 
-       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, *streams, struct stream_struct,
+       tmp = talloc_realloc(mem_ctx, *streams, struct stream_struct,
                                   (*num_streams)+1);
        if (tmp == NULL) {
                return false;
@@ -802,19 +812,8 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
                return map_nt_error_from_unix(errno);
        }
 
-       state.streams = NULL;
-       state.num_streams = 0;
-
-       if (!S_ISDIR(sbuf.st_ex_mode)) {
-               if (!add_one_stream(mem_ctx,
-                                   &state.num_streams, &state.streams,
-                                   "::$DATA", sbuf.st_ex_size,
-                                   SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp,
-                                                          &sbuf))) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
+       state.streams = *pstreams;
+       state.num_streams = *pnum_streams;
        state.mem_ctx = mem_ctx;
        state.handle = handle;
        state.status = NT_STATUS_OK;
@@ -834,7 +833,8 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
 
        *pnum_streams = state.num_streams;
        *pstreams = state.streams;
-       return NT_STATUS_OK;
+
+       return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams);
 }
 
 static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle,
@@ -845,7 +845,7 @@ static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle,
 
 static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
                                    files_struct *fsp, const void *data,
-                                   size_t n, SMB_OFF_T offset)
+                                   size_t n, off_t offset)
 {
         struct stream_io *sio =
                (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
@@ -872,7 +872,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
         if ((offset + n) > ea.value.length-1) {
                uint8 *tmp;
 
-               tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8,
+               tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8,
                                           offset + n + 1);
 
                if (tmp == NULL) {
@@ -908,7 +908,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
 
 static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
                                   files_struct *fsp, void *data,
-                                  size_t n, SMB_OFF_T offset)
+                                  size_t n, off_t offset)
 {
         struct stream_io *sio =
                (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
@@ -940,8 +940,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
 
         /* Attempt to read past EOF. */
         if (length <= offset) {
-                errno = EINVAL;
-                return -1;
+                return 0;
         }
 
         overlap = (offset + n) > length ? (length - offset) : n;
@@ -953,7 +952,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
 
 static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
                                        struct files_struct *fsp,
-                                       SMB_OFF_T offset)
+                                       off_t offset)
 {
        int ret;
        uint8 *tmp;
@@ -979,7 +978,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8,
+       tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8,
                                   offset + 1);
 
        if (tmp == NULL) {
@@ -1018,18 +1017,45 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
        return 0;
 }
 
+static int streams_xattr_fallocate(struct vfs_handle_struct *handle,
+                                       struct files_struct *fsp,
+                                       enum vfs_fallocate_mode mode,
+                                       off_t offset,
+                                       off_t len)
+{
+        struct stream_io *sio =
+               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
+       DEBUG(10, ("streams_xattr_fallocate called for file %s offset %.0f"
+               "len = %.0f\n",
+               fsp_str_dbg(fsp), (double)offset, (double)len));
+
+       if (sio == NULL) {
+               return SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
+       }
+
+       if (!streams_xattr_recheck(sio)) {
+               return errno;
+       }
+
+       /* Let the pwrite code path handle it. */
+       return ENOSYS;
+}
+
+
 static struct vfs_fn_pointers vfs_streams_xattr_fns = {
-       .fs_capabilities = streams_xattr_fs_capabilities,
-       .open = streams_xattr_open,
-       .stat = streams_xattr_stat,
-       .fstat = streams_xattr_fstat,
-       .lstat = streams_xattr_lstat,
-       .pread = streams_xattr_pread,
-       .pwrite = streams_xattr_pwrite,
-       .unlink = streams_xattr_unlink,
-       .rename = streams_xattr_rename,
-        .ftruncate = streams_xattr_ftruncate,
-       .streaminfo = streams_xattr_streaminfo,
+       .fs_capabilities_fn = streams_xattr_fs_capabilities,
+       .open_fn = streams_xattr_open,
+       .stat_fn = streams_xattr_stat,
+       .fstat_fn = streams_xattr_fstat,
+       .lstat_fn = streams_xattr_lstat,
+       .pread_fn = streams_xattr_pread,
+       .pwrite_fn = streams_xattr_pwrite,
+       .unlink_fn = streams_xattr_unlink,
+       .rename_fn = streams_xattr_rename,
+       .ftruncate_fn = streams_xattr_ftruncate,
+       .fallocate_fn = streams_xattr_fallocate,
+       .streaminfo_fn = streams_xattr_streaminfo,
 };
 
 NTSTATUS vfs_streams_xattr_init(void);