s3: Change SMB_VFS_OPEN to take an smb_filename struct
authorTim Prouty <tprouty@samba.org>
Tue, 16 Jun 2009 19:01:13 +0000 (12:01 -0700)
committerTim Prouty <tprouty@samba.org>
Thu, 18 Jun 2009 03:11:53 +0000 (20:11 -0700)
This was a little messy because of all of the vfs modules I had to
touch.  Most of them were pretty straight forward, but the streams
modules required a little attention to handle smb_filename.  Since the
use of smb_filename enables the vfs modules to access the raw,
over-the-wire stream, a little bit of the handling that was being done
by split_ntfs_stream_name has now been shifted into the individual
stream modules.  It may be a little more code, but overall it gives
more flexibility to the streams modules, while also allowing correct
stream handling.

25 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/proto.h
source3/include/vfs.h
source3/modules/vfs_acl_tdb.c
source3/modules/vfs_acl_xattr.c
source3/modules/vfs_audit.c
source3/modules/vfs_cap.c
source3/modules/vfs_catia.c
source3/modules/vfs_commit.c
source3/modules/vfs_default.c
source3/modules/vfs_extd_audit.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_onefs.c
source3/modules/vfs_onefs_shadow_copy.c
source3/modules/vfs_prealloc.c
source3/modules/vfs_preopen.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_streams_depot.c
source3/modules/vfs_streams_xattr.c
source3/modules/vfs_syncops.c
source3/smbd/filename.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/torture/cmd_vfs.c

index 118a5b9..d1000f1 100644 (file)
@@ -122,9 +122,10 @@ static int skel_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dir)
        return vfswrap_closedir(NULL,  dir);
 }
 
-static int skel_open(vfs_handle_struct *handle,  const char *fname, files_struct *fsp, int flags, mode_t mode)
+static int skel_open(vfs_handle_struct *handle,  struct smb_fname *smb_fname,
+                    files_struct *fsp, int flags, mode_t mode)
 {
-       return vfswrap_open(NULL,  fname, flags, mode);
+       return vfswrap_open(NULL, smb_fname, flags, mode);
 }
 
 static int skel_close(vfs_handle_struct *handle, files_struct *fsp)
index a95b5ae..101951b 100644 (file)
@@ -116,9 +116,10 @@ static int skel_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dir)
        return SMB_VFS_NEXT_CLOSEDIR(handle, dir);
 }
 
-static int skel_open(vfs_handle_struct *handle,  const char *fname, files_struct *fsp, int flags, mode_t mode)
+static int skel_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
+                    files_struct *fsp, int flags, mode_t mode)
 {
-       return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 }
 
 static int skel_close(vfs_handle_struct *handle, files_struct *fsp)
index 8435b79..4ae141e 100644 (file)
@@ -6583,6 +6583,7 @@ void send_nt_replies(connection_struct *conn,
                     char *pdata, int datasize);
 bool is_ntfs_stream_name(const char *fname);
 bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname);
+bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname);
 void reply_ntcreate_and_X(struct smb_request *req);
 void reply_ntcancel(struct smb_request *req);
 void reply_ntrename(struct smb_request *req);
index e0e0228..53a4798 100644 (file)
 /* Leave at 25 - not yet released. Add init_search_op call. - sdann */
 /* Leave at 25 - not yet released. Add locking calls. -- zkirsch. */
 /* Leave at 25 - not yet released. Add strict locking calls. -- drichards. */
-/* Changed to version 26 - Plumb struct smb_filename to SMB_VFS_CREATE_FILE. */
+/* Changed to version 26 - Plumb struct smb_filename to SMB_VFS_CREATE_FILE,
+                          SMB_VFS_OPEN. */
 
 #define SMB_VFS_INTERFACE_VERSION 26
 
@@ -330,7 +331,9 @@ struct vfs_ops {
 
                /* File operations */
 
-               int (*open)(struct vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
+               int (*open)(struct vfs_handle_struct *handle,
+                           struct smb_filename *smb_fname, files_struct *fsp,
+                           int flags, mode_t mode);
                NTSTATUS (*create_file)(struct vfs_handle_struct *handle,
                                        struct smb_request *req,
                                        uint16_t root_dir_fid,
index 463250a..e0a5b14 100644 (file)
@@ -549,7 +549,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
 *********************************************************************/
 
 static int open_acl_tdb(vfs_handle_struct *handle,
-                                       const char *fname,
+                                       struct smb_filename *smb_fname,
                                        files_struct *fsp,
                                        int flags,
                                        mode_t mode)
@@ -557,7 +557,17 @@ static int open_acl_tdb(vfs_handle_struct *handle,
        uint32_t access_granted = 0;
        struct security_descriptor *pdesc = NULL;
        bool file_existed = true;
-       NTSTATUS status = get_nt_acl_tdb_internal(handle,
+       char *fname = NULL;
+       NTSTATUS status;
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname,
+                                      &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
+       status = get_nt_acl_tdb_internal(handle,
                                        NULL,
                                        fname,
                                        (OWNER_SECURITY_INFORMATION |
@@ -573,7 +583,7 @@ static int open_acl_tdb(vfs_handle_struct *handle,
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10,("open_acl_tdb: file %s open "
                                "refused with error %s\n",
-                               fname,
+                               smb_fname_str_dbg(smb_fname),
                                nt_errstr(status) ));
                        errno = map_errno_from_nt_status(status);
                        return -1;
@@ -584,10 +594,10 @@ static int open_acl_tdb(vfs_handle_struct *handle,
 
        DEBUG(10,("open_acl_tdb: get_nt_acl_attr_internal for "
                "file %s returned %s\n",
-               fname,
+               smb_fname_str_dbg(smb_fname),
                nt_errstr(status) ));
 
-       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 
        if (!file_existed && fsp->fh->fd != -1) {
                /* File was created. Inherit from parent directory. */
index 05156f8..efcc877 100644 (file)
@@ -417,7 +417,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
 *********************************************************************/
 
 static int open_acl_xattr(vfs_handle_struct *handle,
-                                       const char *fname,
+                                       struct smb_filename *smb_fname,
                                        files_struct *fsp,
                                        int flags,
                                        mode_t mode)
@@ -425,7 +425,17 @@ static int open_acl_xattr(vfs_handle_struct *handle,
        uint32_t access_granted = 0;
        struct security_descriptor *pdesc = NULL;
        bool file_existed = true;
-       NTSTATUS status = get_nt_acl_xattr_internal(handle,
+       char *fname = NULL;
+       NTSTATUS status;
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname,
+                                      &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
+       status = get_nt_acl_xattr_internal(handle,
                                        NULL,
                                        fname,
                                        (OWNER_SECURITY_INFORMATION |
@@ -441,7 +451,7 @@ static int open_acl_xattr(vfs_handle_struct *handle,
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10,("open_acl_xattr: file %s open "
                                "refused with error %s\n",
-                               fname,
+                               smb_fname_str_dbg(smb_fname),
                                nt_errstr(status) ));
                        errno = map_errno_from_nt_status(status);
                        return -1;
@@ -452,10 +462,10 @@ static int open_acl_xattr(vfs_handle_struct *handle,
 
        DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
                "file %s returned %s\n",
-               fname,
+               smb_fname_str_dbg(smb_fname),
                nt_errstr(status) ));
 
-       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 
        if (!file_existed && fsp->fh->fd != -1) {
                /* File was created. Inherit from parent directory. */
index 4000580..2897cef 100644 (file)
@@ -33,7 +33,7 @@ static void audit_disconnect(vfs_handle_struct *handle);
 static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
 static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
 static int audit_rmdir(vfs_handle_struct *handle, const char *path);
-static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
+static int audit_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode);
 static int audit_close(vfs_handle_struct *handle, files_struct *fsp);
 static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
 static int audit_unlink(vfs_handle_struct *handle, const char *path);
@@ -187,14 +187,16 @@ static int audit_rmdir(vfs_handle_struct *handle, const char *path)
        return result;
 }
 
-static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle,
+                     struct smb_filename *smb_fname, files_struct *fsp,
+                     int flags, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 
        syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", 
-              fname, result,
+              smb_fname_str_dbg(smb_fname), result,
               ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", 
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : "");
index e26d29d..4525fa1 100644 (file)
@@ -106,16 +106,30 @@ static int cap_rmdir(vfs_handle_struct *handle, const char *path)
        return SMB_VFS_NEXT_RMDIR(handle, cappath);
 }
 
-static int cap_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
+static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
+                   files_struct *fsp, int flags, mode_t mode)
 {
-       char *cappath = capencode(talloc_tos(), fname);
+       char *cappath;
+       char *tmp_base_name = NULL;
+       int ret;
+
+       cappath = capencode(talloc_tos(), smb_fname->base_name);
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       DEBUG(3,("cap: cap_open for %s\n", fname));
-       return SMB_VFS_NEXT_OPEN(handle, cappath, fsp, flags, mode);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = cappath;
+
+       DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname)));
+       ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(cappath);
+
+       return ret;
 }
 
 static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
index 2870254..8d1c87a 100644 (file)
@@ -133,18 +133,30 @@ static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle,
 }
 
 static int catia_open(vfs_handle_struct *handle,
-                     const char *fname,
+                     struct smb_filename *smb_fname,
                      files_struct *fsp,
                      int flags,
                      mode_t mode)
 {
-       char *name = to_unix(talloc_tos(), fname);
+       char *name;
+       char *tmp_base_name;
+       int ret;
 
+       name = to_unix(talloc_tos(), smb_fname->base_name);
        if (!name) {
                errno = ENOMEM;
                return -1;
        }
-        return SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = name;
+
+       ret = SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(name);
+
+       return ret;
 }
 
 static int catia_rename(vfs_handle_struct *handle,
index c22e816..6c36322 100644 (file)
@@ -167,7 +167,7 @@ static int commit_connect(
 
 static int commit_open(
        vfs_handle_struct * handle,
-       const char *        fname,
+       struct smb_filename *smb_fname,
        files_struct *      fsp,
        int                 flags,
        mode_t              mode)
@@ -179,7 +179,7 @@ static int commit_open(
 
         /* Don't bother with read-only files. */
         if ((flags & O_ACCMODE) == O_RDONLY) {
-                return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+                return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
         }
 
         /* Read and check module configuration */
@@ -208,7 +208,7 @@ static int commit_open(
                 }
         }
 
-        fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+        fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
        if (fd == -1) {
                VFS_REMOVE_FSP_EXTENSION(handle, fsp);
                return fd;
index 28adce5..0e7ba05 100644 (file)
@@ -214,13 +214,31 @@ static void vfswrap_init_search_op(vfs_handle_struct *handle,
 
 /* File operations */
 
-static int vfswrap_open(vfs_handle_struct *handle,  const char *fname,
-       files_struct *fsp, int flags, mode_t mode)
+static int vfswrap_open(vfs_handle_struct *handle,
+                       struct smb_filename *smb_fname,
+                       files_struct *fsp, int flags, mode_t mode)
 {
        int result;
+       NTSTATUS status;
+       char *fname = NULL;
 
        START_PROFILE(syscall_open);
+
+       /*
+        * XXX: Should an error be returned if there is a stream rather than
+        * trying to open a filename with a ':'?
+        */
+       status = get_full_smb_filename(talloc_tos(), smb_fname,
+                                      &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
        result = sys_open(fname, flags, mode);
+
+       TALLOC_FREE(fname);
+
        END_PROFILE(syscall_open);
        return result;
 }
index b59a780..763f154 100644 (file)
@@ -36,7 +36,7 @@ static void audit_disconnect(vfs_handle_struct *handle);
 static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
 static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
 static int audit_rmdir(vfs_handle_struct *handle, const char *path);
-static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
+static int audit_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode);
 static int audit_close(vfs_handle_struct *handle, files_struct *fsp);
 static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
 static int audit_unlink(vfs_handle_struct *handle, const char *path);
@@ -216,21 +216,23 @@ static int audit_rmdir(vfs_handle_struct *handle, const char *path)
        return result;
 }
 
-static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle,
+                     struct smb_filename *smb_fname, files_struct *fsp,
+                     int flags, mode_t mode)
 {
        int result;
 
-       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 
        if (lp_syslog() > 0) {
                syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n",
-                      fname, result,
+                      smb_fname_str_dbg(smb_fname), result,
                       ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "",
                       (result < 0) ? "failed: " : "",
                       (result < 0) ? strerror(errno) : "");
        }
        DEBUG(2, ("vfs_extd_audit: open %s %s %s\n",
-              fname,
+              smb_fname_str_dbg(smb_fname),
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : ""));
 
index e2d08b4..5558b2f 100644 (file)
@@ -111,7 +111,7 @@ static int smb_full_audit_closedir(vfs_handle_struct *handle,
 static void smb_full_audit_init_search_op(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp);
 static int smb_full_audit_open(vfs_handle_struct *handle,
-                     const char *fname, files_struct *fsp, int flags, mode_t mode);
+                     struct smb_filename *smb_fnmae, files_struct *fsp, int flags, mode_t mode);
 static NTSTATUS smb_full_audit_create_file(vfs_handle_struct *handle,
                                      struct smb_request *req,
                                      uint16_t root_dir_fid,
@@ -1179,15 +1179,16 @@ static void smb_full_audit_init_search_op(vfs_handle_struct *handle,
 }
 
 static int smb_full_audit_open(vfs_handle_struct *handle,
-                     const char *fname, files_struct *fsp, int flags, mode_t mode)
+                              struct smb_filename *smb_fname,
+                              files_struct *fsp, int flags, mode_t mode)
 {
        int result;
        
-       result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 
        do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s",
               ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r",
-              fname);
+              smb_fname_str_dbg(smb_fname));
 
        return result;
 }
index 7414f16..c143fcf 100644 (file)
@@ -47,12 +47,13 @@ static int onefs_mkdir(vfs_handle_struct *handle, const char *path,
        return SMB_VFS_NEXT_MKDIR(handle, path, mode);
 }
 
-static int onefs_open(vfs_handle_struct *handle, const char *fname,
+static int onefs_open(vfs_handle_struct *handle,
+                     struct smb_filename *smb_fname,
                      files_struct *fsp, int flags, mode_t mode)
 {
        /* SMB_VFS_OPEN should never be called in vfs_onefs */
        SMB_ASSERT(false);
-       return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 }
 
 static ssize_t onefs_sendfile(vfs_handle_struct *handle, int tofd,
index 3d4ffc9..45860fa 100644 (file)
@@ -214,12 +214,13 @@ onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path)
 }
 
 static int
-onefs_shadow_copy_open(vfs_handle_struct *handle, const char *path,
-                      files_struct *fsp, int flags, mode_t mode)
+onefs_shadow_copy_open(vfs_handle_struct *handle,
+                      struct smb_filename *smb_fname, files_struct *fsp,
+                      int flags, mode_t mode)
 {
-       SHADOW_NEXT(OPEN,
-                   (handle, cpath ?: path, fsp, flags, mode),
-                   int);
+       SHADOW_NEXT_SMB_FNAME(OPEN,
+                             (handle, smb_fname, fsp, flags, mode),
+                             int);
 }
 
 static NTSTATUS
index 299f654..2f65e94 100644 (file)
@@ -108,7 +108,7 @@ static int prealloc_connect(
 }
 
 static int prealloc_open(vfs_handle_struct* handle,
-                       const char *        fname,
+                       struct smb_filename *smb_fname,
                        files_struct *      fsp,
                        int                 flags,
                        mode_t              mode)
@@ -127,7 +127,7 @@ static int prealloc_open(vfs_handle_struct* handle,
        }
 
        *fext = '\0';
-       dot = strrchr(fname, '.');
+       dot = strrchr(smb_fname->base_name, '.');
        if (dot && *++dot) {
                if (strlen(dot) < sizeof(fext)) {
                        strncpy(fext, dot, sizeof(fext));
@@ -152,7 +152,7 @@ static int prealloc_open(vfs_handle_struct* handle,
                goto normal_open;
        }
 
-       fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
        if (fd < 0) {
                return fd;
        }
@@ -171,7 +171,8 @@ static int prealloc_open(vfs_handle_struct* handle,
 
                DEBUG(module_debug,
                        ("%s: preallocating %s (fd=%d) to %lld bytes\n",
-                       MODULE, fname, fd, (long long)size));
+                           MODULE, smb_fname_str_dbg(smb_fname), fd,
+                           (long long)size));
 
                *psize = size;
                if (preallocate_space(fd, *psize) < 0) {
@@ -186,8 +187,8 @@ normal_open:
         * preallocation.
         */
        DEBUG(module_debug, ("%s: skipping preallocation for %s\n",
-                   MODULE, fname));
-       return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+               MODULE, smb_fname_str_dbg(smb_fname)));
+       return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 }
 
 static int prealloc_ftruncate(vfs_handle_struct * handle,
index 25b9e7f..dcc1ae1 100644 (file)
@@ -371,21 +371,22 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
        return true;
 }
 
-static int preopen_open(vfs_handle_struct *handle, const char *fname,
-                       files_struct *fsp, int flags, mode_t mode)
+static int preopen_open(vfs_handle_struct *handle,
+                       struct smb_filename *smb_fname, files_struct *fsp,
+                       int flags, mode_t mode)
 {
        struct preopen_state *state;
        int res;
        unsigned long num;
 
-       DEBUG(10, ("preopen_open called on %s\n", fname));
+       DEBUG(10, ("preopen_open called on %s\n", smb_fname_str_dbg(smb_fname)));
 
        state = preopen_state_get(handle);
        if (state == NULL) {
-               return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+               return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
        }
 
-       res = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       res = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
        if (res == -1) {
                return -1;
        }
@@ -394,15 +395,15 @@ static int preopen_open(vfs_handle_struct *handle, const char *fname,
                return res;
        }
 
-       if (!is_in_path(fname, state->preopen_names, true)) {
+       if (!is_in_path(smb_fname->base_name, state->preopen_names, true)) {
                DEBUG(10, ("%s does not match the preopen:names list\n",
-                          fname));
+                          smb_fname_str_dbg(smb_fname)));
                return res;
        }
 
        TALLOC_FREE(state->template_fname);
        state->template_fname = talloc_asprintf(
-               state, "%s/%s", fsp->conn->connectpath, fname);
+               state, "%s/%s", fsp->conn->connectpath, smb_fname->base_name);
 
        if (state->template_fname == NULL) {
                return res;
index 030d3e2..7b5b85d 100644 (file)
@@ -115,6 +115,28 @@ static inline bool shadow_copy2_match_name(const char *name)
        } \
 } while (0)
 
+#define _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, extra) do { \
+       if (shadow_copy2_match_name(smb_fname->base_name)) { \
+               char *name2; \
+               char *smb_base_name_tmp = NULL; \
+               rtype ret; \
+               name2 = convert_shadow2_name(handle, smb_fname->base_name); \
+               if (name2 == NULL) { \
+                       errno = EINVAL; \
+                       return eret; \
+               } \
+               smb_base_name_tmp = smb_fname->base_name; \
+               smb_fname->base_name = name2; \
+               ret = SMB_VFS_NEXT_ ## op args; \
+               smb_fname->base_name = smb_base_name_tmp; \
+               talloc_free(name2); \
+               if (ret != eret) extra; \
+               return ret; \
+       } else { \
+               return SMB_VFS_NEXT_ ## op args; \
+       } \
+} while (0)
+
 /*
   convert a name to the shadow directory: NTSTATUS-specific handling
  */
@@ -143,6 +165,8 @@ static inline bool shadow_copy2_match_name(const char *name)
 
 #define SHADOW2_NEXT(op, args, rtype, eret) _SHADOW2_NEXT(op, args, rtype, eret, )
 
+#define SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret) _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, )
+
 #define SHADOW2_NEXT2(op, args) do { \
        if (shadow_copy2_match_name(oldname) || shadow_copy2_match_name(newname)) { \
                errno = EROFS; \
@@ -337,9 +361,12 @@ static int shadow_copy2_link(vfs_handle_struct *handle,
 }
 
 static int shadow_copy2_open(vfs_handle_struct *handle,
-                            const char *fname, files_struct *fsp, int flags, mode_t mode)
+                            struct smb_filename *smb_fname, files_struct *fsp,
+                            int flags, mode_t mode)
 {
-       SHADOW2_NEXT(OPEN, (handle, name, fsp, flags, mode), int, -1);
+       SHADOW2_NEXT_SMB_FNAME(OPEN,
+                              (handle, smb_fname, fsp, flags, mode),
+                              int, -1);
 }
 
 static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
index 72affe4..7d37af0 100644 (file)
@@ -267,6 +267,69 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
        TALLOC_FREE(result);
        return NULL;
 }
+/**
+ * Given a stream name, populate smb_fname_out with the actual location of the
+ * stream.
+ */
+static NTSTATUS stream_smb_fname(vfs_handle_struct *handle,
+                                const struct smb_filename *smb_fname,
+                                struct smb_filename **smb_fname_out,
+                                bool create_dir)
+{
+       char *dirname, *stream_fname;
+       const char *stype;
+       NTSTATUS status;
+
+       *smb_fname_out = NULL;
+
+       dirname = stream_dir(handle, smb_fname->base_name, NULL, create_dir);
+
+       if (dirname == NULL) {
+               status = map_nt_error_from_unix(errno);
+               goto fail;
+       }
+
+       stype = strchr_m(smb_fname->stream_name + 1, ':');
+
+       stream_fname = talloc_asprintf(talloc_tos(), "%s/%s", dirname,
+                                      smb_fname->stream_name);
+
+       if (stream_fname == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+
+       if (stype == NULL) {
+               /* Append an explicit stream type if one wasn't specified. */
+               stream_fname = talloc_asprintf(talloc_tos(), "%s:$DATA",
+                                              stream_fname);
+               if (stream_fname == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto fail;
+               }
+       } else {
+               /* Normalize the stream type to upercase. */
+               strupper_m(strrchr_m(stream_fname, ':') + 1);
+       }
+
+       DEBUG(10, ("stream filename = %s\n", stream_fname));
+
+       /* Create an smb_filename with stream_name == NULL. */
+       status = create_synthetic_smb_fname(talloc_tos(),
+                                           stream_fname,
+                                           NULL, NULL,
+                                           smb_fname_out);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+
+ fail:
+       DEBUG(5, ("stream_name failed: %s\n", strerror(errno)));
+       TALLOC_FREE(*smb_fname_out);
+       return status;
+}
 
 static char *stream_name(vfs_handle_struct *handle, const char *fname,
                         bool create_dir)
@@ -422,50 +485,52 @@ static int streams_depot_lstat(vfs_handle_struct *handle, const char *fname,
        return ret;
 }
 
-static int streams_depot_open(vfs_handle_struct *handle,  const char *fname,
+static int streams_depot_open(vfs_handle_struct *handle,
+                             struct smb_filename *smb_fname,
                              files_struct *fsp, int flags, mode_t mode)
 {
-       TALLOC_CTX *frame;
-       char *base = NULL;
-       char *sname = NULL;
+       struct smb_filename *smb_fname_stream = NULL;
        SMB_STRUCT_STAT base_sbuf;
-       char *stream_fname;
+       NTSTATUS status;
        int ret = -1;
 
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+               return ret;
        }
 
-       frame = talloc_stackframe();
+       /* If the default stream is requested, just open the base file. */
+       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
+               char *tmp_stream_name;
 
-       if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname,
-                                                   &base, &sname))) {
-               errno = ENOMEM;
-               goto done;
-       }
+               tmp_stream_name = smb_fname->stream_name;
+               smb_fname->stream_name = NULL;
 
-       if (!sname) {
-               ret = SMB_VFS_NEXT_OPEN(handle, base, fsp, flags, mode);
-               goto done;
+               ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+
+               smb_fname->stream_name = tmp_stream_name;
+
+               return ret;
        }
 
-       ret = SMB_VFS_NEXT_STAT(handle, base, &base_sbuf);
+       /* Ensure the base file still exists. */
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname->base_name, &base_sbuf);
 
        if (ret == -1) {
                goto done;
        }
 
-       TALLOC_FREE(base);
-
-       stream_fname = stream_name(handle, fname, true);
-       if (stream_fname == NULL) {
+       status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
                goto done;
        }
 
-       ret = SMB_VFS_NEXT_OPEN(handle, stream_fname, fsp, flags, mode);
+       ret = SMB_VFS_NEXT_OPEN(handle, smb_fname_stream, fsp, flags, mode);
 
  done:
-       TALLOC_FREE(frame);
+       TALLOC_FREE(smb_fname_stream);
        return ret;
 }
 
index ebc51e7..715e1a7 100644 (file)
@@ -88,6 +88,43 @@ static ssize_t get_xattr_size(connection_struct *conn,
        return result;
 }
 
+/**
+ * Given a stream name, populate xattr_name with the xattr name to use for
+ * accessing the stream.
+ */
+static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx,
+                                      const char *stream_name,
+                                      char **xattr_name)
+{
+       char *stype;
+
+       stype = strchr_m(stream_name + 1, ':');
+
+       *xattr_name = talloc_asprintf(ctx, "%s%s",
+                                     SAMBA_XATTR_DOSSTREAM_PREFIX,
+                                     stream_name + 1);
+       if (*xattr_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (stype == NULL) {
+               /* Append an explicit stream type if one wasn't specified. */
+               *xattr_name = talloc_asprintf(ctx, "%s:$DATA",
+                                              *xattr_name);
+               if (*xattr_name == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       } else {
+               /* Normalize the stream type to upercase. */
+               strupper_m(strrchr_m(*xattr_name, ':') + 1);
+       }
+
+       DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
+                  stream_name));
+
+       return NT_STATUS_OK;
+}
+
 static bool streams_xattr_recheck(struct stream_io *sio)
 {
        NTSTATUS status;
@@ -277,43 +314,54 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname,
        return result;
 }
 
-static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
+static int streams_xattr_open(vfs_handle_struct *handle,
+                             struct smb_filename *smb_fname,
                              files_struct *fsp, int flags, mode_t mode)
 {
-       TALLOC_CTX *frame;
        NTSTATUS status;
+       struct smb_filename *smb_fname_base = NULL;
        struct stream_io *sio;
-       char *base, *sname;
        struct ea_struct ea;
-       char *xattr_name;
+       char *xattr_name = NULL;
        int baseflags;
        int hostfd = -1;
 
-       DEBUG(10, ("streams_xattr_open called for %s\n", fname));
+       DEBUG(10, ("streams_xattr_open called for %s\n",
+                  smb_fname_str_dbg(smb_fname)));
 
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
        }
 
-       frame = talloc_stackframe();
+       /* If the default stream is requested, just open the base file. */
+       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
+               char *tmp_stream_name;
+               int ret;
 
-       status = split_ntfs_stream_name(talloc_tos(), fname,
-                                       &base, &sname);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = EINVAL;
-               goto fail;
+               tmp_stream_name = smb_fname->stream_name;
+               smb_fname->stream_name = NULL;
+
+               ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+
+               smb_fname->stream_name = tmp_stream_name;
+
+               return ret;
        }
 
-       if (sname == NULL) {
-               hostfd = SMB_VFS_NEXT_OPEN(handle, base, fsp, flags, mode);
-               talloc_free(frame);
-               return hostfd;
+       status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
+                                       &xattr_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto fail;
        }
 
-       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
-                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
-       if (xattr_name == NULL) {
-               errno = ENOMEM;
+       /* Create an smb_filename with stream_name == NULL. */
+       status = create_synthetic_smb_fname(talloc_tos(),
+                                           smb_fname->base_name,
+                                           NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
                goto fail;
        }
 
@@ -326,7 +374,10 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
         baseflags &= ~O_EXCL;
         baseflags &= ~O_CREAT;
 
-        hostfd = SMB_VFS_OPEN(handle->conn, base, fsp, baseflags, mode);
+        hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
+                             baseflags, mode);
+
+       TALLOC_FREE(smb_fname_base);
 
         /* It is legit to open a stream on a directory, but the base
          * fd has to be read-only.
@@ -334,7 +385,7 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
         if ((hostfd == -1) && (errno == EISDIR)) {
                 baseflags &= ~O_ACCMODE;
                 baseflags |= O_RDONLY;
-                hostfd = SMB_VFS_OPEN(handle->conn, fname, fsp, baseflags,
+                hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags,
                                      mode);
         }
 
@@ -342,8 +393,8 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                goto fail;
         }
 
-       status = get_ea_value(talloc_tos(), handle->conn, NULL, base,
-                             xattr_name, &ea);
+       status = get_ea_value(talloc_tos(), handle->conn, NULL,
+                             smb_fname->base_name, xattr_name, &ea);
 
        DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
 
@@ -355,7 +406,7 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                 * file for us.
                 */
                DEBUG(10, ("streams_xattr_open: base file %s not around, "
-                          "returning ENOENT\n", base));
+                          "returning ENOENT\n", smb_fname->base_name));
                errno = ENOENT;
                goto fail;
        }
@@ -372,7 +423,7 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                         char null = '\0';
 
                        DEBUG(10, ("creating attribute %s on file %s\n",
-                                  xattr_name, base));
+                                  xattr_name, smb_fname->base_name));
 
                        if (fsp->base_fsp->fh->fd != -1) {
                                if (SMB_VFS_FSETXATTR(
@@ -383,8 +434,8 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                                }
                        } else {
                                if (SMB_VFS_SETXATTR(
-                                       handle->conn, base, xattr_name,
-                                       &null, sizeof(null),
+                                       handle->conn, smb_fname->base_name,
+                                       xattr_name, &null, sizeof(null),
                                        flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
                                        goto fail;
                                }
@@ -403,8 +454,8 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                        }
                } else {
                        if (SMB_VFS_SETXATTR(
-                                       handle->conn, base, xattr_name,
-                                       &null, sizeof(null),
+                                       handle->conn, smb_fname->base_name,
+                                       xattr_name, &null, sizeof(null),
                                        flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
                                goto fail;
                        }
@@ -422,7 +473,7 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
                                        xattr_name);
         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-                                 base);
+                                 smb_fname->base_name);
        sio->fsp_name_ptr = fsp->fsp_name;
        sio->handle = handle;
        sio->fsp = fsp;
@@ -432,7 +483,6 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                goto fail;
        }
 
-       TALLOC_FREE(frame);
        return hostfd;
 
  fail:
@@ -444,7 +494,6 @@ static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
                SMB_VFS_CLOSE(fsp);
        }
 
-       TALLOC_FREE(frame);
        return -1;
 }
 
index d3f7868..562195c 100644 (file)
@@ -104,6 +104,19 @@ static void syncops_name(const char *name)
        }
 }
 
+/*
+  sync two meta data changes for 1 names
+ */
+static void syncops_smb_fname(struct smb_filename *smb_fname)
+{
+       char *parent;
+       parent = parent_dir(NULL, smb_fname->base_name);
+       if (parent) {
+               syncops_sync_directory(parent);
+               talloc_free(parent);
+       }
+}
+
 
 /*
   rename needs special handling, as we may need to fsync two directories
@@ -125,6 +138,12 @@ static int syncops_rename(vfs_handle_struct *handle,
        return ret; \
 } while (0)
 
+#define SYNCOPS_NEXT_SMB_FNAME(op, fname, args) do {   \
+       int ret = SMB_VFS_NEXT_ ## op args; \
+       if (ret == 0 && fname) syncops_smb_fname(fname); \
+       return ret; \
+} while (0)
+
 static int syncops_symlink(vfs_handle_struct *handle,
                           const char *oldname, const char *newname)
 {
@@ -138,9 +157,11 @@ static int syncops_link(vfs_handle_struct *handle,
 }
 
 static int syncops_open(vfs_handle_struct *handle,
-                       const char *fname, files_struct *fsp, int flags, mode_t mode)
+                       struct smb_filename *smb_fname, files_struct *fsp,
+                       int flags, mode_t mode)
 {
-       SYNCOPS_NEXT(OPEN, (flags&O_CREAT?fname:NULL), (handle, fname, fsp, flags, mode));
+       SYNCOPS_NEXT_SMB_FNAME(OPEN, (flags&O_CREAT?smb_fname:NULL),
+                              (handle, smb_fname, fsp, flags, mode));
 }
 
 static int syncops_unlink(vfs_handle_struct *handle, const char *fname)
index 0f69ce4..456caf5 100644 (file)
@@ -115,8 +115,6 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
 {
        struct smb_filename smb_fname_loc;
 
-       SMB_ASSERT(psbuf);
-
        ZERO_STRUCT(smb_fname_loc);
 
        /* Setup the base_name/stream_name. */
@@ -124,7 +122,8 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
        smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name);
 
        /* Copy the psbuf if one was given. */
-       smb_fname_loc.st = *psbuf;
+       if (psbuf)
+               smb_fname_loc.st = *psbuf;
 
        /* Let copy_smb_filename() do the heavy lifting. */
        return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out);
index d2a052d..c4d0374 100644 (file)
@@ -318,6 +318,22 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
 }
 
 /****************************************************************************
+ Returns true if the filename's stream == "::$DATA"
+ ***************************************************************************/
+bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
+{
+       if (lp_posix_pathnames()) {
+               return false;
+       }
+
+       if (!smb_fname->stream_name) {
+               return false;
+       }
+
+       return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0;
+}
+
+/****************************************************************************
  Reply to an NT create and X call on a pipe
 ****************************************************************************/
 
index 7b2fc19..5d82738 100644 (file)
@@ -119,7 +119,7 @@ static NTSTATUS check_open_rights(struct connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS fd_open(struct connection_struct *conn,
-                   const char *fname, 
+                   struct smb_filename *smb_fname,
                    files_struct *fsp,
                    int flags,
                    mode_t mode)
@@ -137,7 +137,7 @@ static NTSTATUS fd_open(struct connection_struct *conn,
        }
 #endif
 
-       fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
+       fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
        if (fsp->fh->fd == -1) {
                status = map_nt_error_from_unix(errno);
                if (errno == EMFILE) {
@@ -155,7 +155,7 @@ static NTSTATUS fd_open(struct connection_struct *conn,
        }
 
        DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
-                   fname, flags, (int)mode, fsp->fh->fd,
+                 smb_fname_str_dbg(smb_fname), flags, (int)mode, fsp->fh->fd,
                (fsp->fh->fd == -1) ? strerror(errno) : "" ));
 
        return status;
@@ -422,7 +422,7 @@ static NTSTATUS open_file(files_struct *fsp,
                }
 
                /* Actually do the open */
-               status = fd_open(conn, path, fsp, local_flags, unx_mode);
+               status = fd_open(conn, smb_fname, fsp, local_flags, unx_mode);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
                                 "(flags=%d)\n", smb_fname_str_dbg(smb_fname),
index 1664f9a..f1f4aed 100644 (file)
@@ -236,6 +236,8 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
        mode_t mode;
        const char *flagstr;
        files_struct *fsp;
+       struct smb_filename *smb_fname = NULL;
+       NTSTATUS status;
 
        mode = 00400;
 
@@ -328,7 +330,16 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
        }
        fsp->conn = vfs->conn;
 
-       fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, argv[1], fsp, flags, mode);
+       status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               SAFE_FREE(fsp->fsp_name);
+               SAFE_FREE(fsp);
+               return status;
+       }
+
+       fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode);
+       TALLOC_FREE(smb_fname);
        if (fsp->fh->fd == -1) {
                printf("open: error=%d (%s)\n", errno, strerror(errno));
                SAFE_FREE(fsp->fh);