s3: Plumb smb_filename through SMB_VFS_STAT and SMB_VFS_LSTAT
authorTim Prouty <tprouty@samba.org>
Mon, 22 Jun 2009 22:26:56 +0000 (15:26 -0700)
committerTim Prouty <tprouty@samba.org>
Thu, 25 Jun 2009 04:15:25 +0000 (21:15 -0700)
This patch introduces two new temporary helper functions
vfs_stat_smb_fname and vfs_lstat_smb_fname.  They basically allowed me
to call the new smb_filename version of stat, while avoiding plumbing
it through callers that are still too inconvenient.  As the conversion
moves along, I will be able to remove callers of this, with the goal
being to remove all callers.

There was also a bug in create_synthetic_smb_fname_split (also a
temporary utility function) that caused it to incorrectly handle
filenames with ':'s in them when in posix mode.  This is now fixed.

38 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/proto.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/nfs4_acls.c
source3/modules/vfs_acl_tdb.c
source3/modules/vfs_acl_xattr.c
source3/modules/vfs_afsacl.c
source3/modules/vfs_cap.c
source3/modules/vfs_catia.c
source3/modules/vfs_default.c
source3/modules/vfs_fake_perms.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_gpfs.c
source3/modules/vfs_hpuxacl.c
source3/modules/vfs_recycle.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_solarisacl.c
source3/modules/vfs_streams_depot.c
source3/modules/vfs_streams_xattr.c
source3/modules/vfs_xattr_tdb.c
source3/smbd/close.c
source3/smbd/dir.c
source3/smbd/dosmode.c
source3/smbd/file_access.c
source3/smbd/fileio.c
source3/smbd/filename.c
source3/smbd/msdfs.c
source3/smbd/notify.c
source3/smbd/open.c
source3/smbd/posix_acls.c
source3/smbd/reply.c
source3/smbd/service.c
source3/smbd/statcache.c
source3/smbd/trans2.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c

index d1000f15b973503bd37d606ccc72e3baa853665b..ee8a3d8f7190595bc55b22b29258b0c9691ca306 100644 (file)
@@ -179,9 +179,9 @@ static int skel_fsync(vfs_handle_struct *handle, files_struct *fsp)
        return vfswrap_fsync(NULL, fsp);
 }
 
-static int skel_stat(vfs_handle_struct *handle,  const char *fname, SMB_STRUCT_STAT *sbuf)
+static int skel_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       return vfswrap_stat(NULL,  fname, sbuf);
+       return vfswrap_stat(NULL, smb_fname);
 }
 
 static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
@@ -189,9 +189,9 @@ static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_S
        return vfswrap_fstat(NULL, fsp, sbuf);
 }
 
-static int skel_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf)
+static int skel_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       return vfswrap_lstat(NULL,  path, sbuf);
+       return vfswrap_lstat(NULL, smb_fname);
 }
 
 static int skel_unlink(vfs_handle_struct *handle,  const char *path)
index 101951b0f956301e10ef79d2db549e90adf20471..10b10b88d6f64e59d440432d77c785018d3a52a4 100644 (file)
@@ -172,9 +172,9 @@ static int skel_fsync(vfs_handle_struct *handle, files_struct *fsp)
        return SMB_VFS_NEXT_FSYNC(handle, fsp);
 }
 
-static int skel_stat(vfs_handle_struct *handle,  const char *fname, SMB_STRUCT_STAT *sbuf)
+static int skel_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       return SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       return SMB_VFS_NEXT_STAT(handle, smb_fname);
 }
 
 static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
@@ -182,9 +182,9 @@ static int skel_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_S
        return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
 }
 
-static int skel_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf)
+static int skel_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       return SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
+       return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
 }
 
 static int skel_unlink(vfs_handle_struct *handle,  const char *path)
index ffd285859452902dacd22de58fc39d2deeffffe8..d55d6c197646f0cfbcfeeaa719b96c0c3d07dfea 100644 (file)
@@ -3508,7 +3508,6 @@ bool release_posix_lock_posix_flavour(files_struct *fsp,
 
 /* The following definitions come from modules/vfs_default.c  */
 
-int vfswrap_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf);
 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size);
 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size);
 NTSTATUS vfs_default_init(void);
@@ -6336,11 +6335,13 @@ NTSTATUS close_fake_file(struct smb_request *req, files_struct *fsp);
 /* The following definitions come from smbd/file_access.c  */
 
 bool can_access_file_acl(struct connection_struct *conn,
-                               const char * fname,
-                               uint32_t access_mask);
+                        const struct smb_filename *smb_fname,
+                        uint32_t access_mask);
 bool can_delete_file_in_directory(connection_struct *conn,
-                                 const struct smb_filename *smb_fname);
-bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint32 access_mask);
+                                 struct smb_filename *smb_fname);
+bool can_access_file_data(connection_struct *conn,
+                         const struct smb_filename *smb_fname,
+                         uint32 access_mask);
 bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf);
 bool directory_has_default_acl(connection_struct *conn, const char *fname);
 
@@ -6366,12 +6367,16 @@ NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_f
                              char **full_name);
 NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
                                    const char *stream_name,
-                                   SMB_STRUCT_STAT *psbuf,
+                                   const SMB_STRUCT_STAT *psbuf,
                                    struct smb_filename **smb_fname_out);
 NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
                                          const char *fname,
-                                         SMB_STRUCT_STAT *psbuf,
+                                         const SMB_STRUCT_STAT *psbuf,
                                          struct smb_filename **smb_fname_out);
+int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
+                      SMB_STRUCT_STAT *psbuf);
+int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
+                       SMB_STRUCT_STAT *psbuf);
 const char *smb_fname_str_dbg(const struct smb_filename *smb_fname);
 NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
                           const struct smb_filename *smb_fname_in,
@@ -7137,8 +7142,6 @@ void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
 bool smbd_vfs_init(connection_struct *conn);
-bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st);
-bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf);
 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname);
 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count);
 ssize_t vfs_pread_data(files_struct *fsp, char *buf,
index 53a4798d3750c8153203a34b2be514d256a7c66e..2a0c5ec805f0a849fbbe103a862c31a90c460c3e 100644 (file)
 /* 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,
-                          SMB_VFS_OPEN. */
+                          SMB_VFS_OPEN, SMB_VFS_STAT, SMB_VFS_LSTAT. */
 
 #define SMB_VFS_INTERFACE_VERSION 26
 
@@ -359,9 +359,9 @@ struct vfs_ops {
                ssize_t (*recvfile)(struct vfs_handle_struct *handle, int fromfd, files_struct *tofsp, SMB_OFF_T offset, size_t count);
                int (*rename)(struct vfs_handle_struct *handle, const char *oldname, const char *newname);
                int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp);
-               int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf);
+               int (*stat)(struct vfs_handle_struct *handle, struct smb_filename *smb_fname);
                int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_STAT *sbuf);
-               int (*lstat)(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf);
+               int (*lstat)(struct vfs_handle_struct *handle, struct smb_filename *smb_filename);
                uint64_t (*get_alloc_size)(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_STAT *sbuf);
                int (*unlink)(struct vfs_handle_struct *handle, const char *path);
                int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode);
index d888361dc41b632b65777a23b0349f9d16ba483e..b0a0737aacbb3efc159ab54e0ab6ae548b72dc6f 100644 (file)
@@ -60,9 +60,9 @@
 #define SMB_VFS_RECVFILE(fromfd, tofsp, offset, count) ((tofsp)->conn->vfs.ops.recvfile((tofsp)->conn->vfs.handles.recvfile, (fromfd), (tofsp), (offset), (count)))
 #define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (old), (new)))
 #define SMB_VFS_FSYNC(fsp) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp)))
-#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf)))
+#define SMB_VFS_STAT(conn, smb_fname) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (smb_fname)))
 #define SMB_VFS_FSTAT(fsp, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp), (sbuf)))
-#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_LSTAT(conn, smb_fname) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (smb_fname)))
 #define SMB_VFS_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs.ops.get_alloc_size((conn)->vfs.handles.get_alloc_size, (fsp), (sbuf)))
 #define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (path)))
 #define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (path), (mode)))
 #define SMB_VFS_OPAQUE_RECVFILE(fromfd, tofsp, offset, count) ((tofsp)->conn->vfs_opaque.ops.recvfile((tofsp)->conn->vfs_opaque.handles.recvfile, (fromfd), (tofsp), (offset), (count)))
 #define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (old), (new)))
 #define SMB_VFS_OPAQUE_FSYNC(fsp) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp)))
-#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf)))
+#define SMB_VFS_OPAQUE_STAT(conn, smb_fname) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (smb_fname)))
 #define SMB_VFS_OPAQUE_FSTAT(fsp, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp), (sbuf)))
-#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_OPAQUE_LSTAT(conn, smb_fname) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (smb_fname)))
 #define SMB_VFS_OPAQUE_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs_opaque.ops.get_alloc_size((conn)->vfs_opaque.handles.get_alloc_size, (fsp), (sbuf)))
 #define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (path)))
 #define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (path), (mode)))
 #define SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, count) ((handle)->vfs_next.ops.recvfile((handle)->vfs_next.handles.recvfile, (fromfd), (tofsp), (offset), (count)))
 #define SMB_VFS_NEXT_RENAME(handle, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (old), (new)))
 #define SMB_VFS_NEXT_FSYNC(handle, fsp) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp)))
-#define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf)))
+#define SMB_VFS_NEXT_STAT(handle, smb_fname) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (smb_fname)))
 #define SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp), (sbuf)))
-#define SMB_VFS_NEXT_LSTAT(handle, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_NEXT_LSTAT(handle, smb_fname) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (smb_fname)))
 #define SMB_VFS_NEXT_GET_ALLOC_SIZE(conn, fsp, sbuf) ((conn)->vfs_next.ops.get_alloc_size((conn)->vfs_next.handles.get_alloc_size, (fsp), (sbuf)))
 #define SMB_VFS_NEXT_UNLINK(handle, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (path)))
 #define SMB_VFS_NEXT_CHMOD(handle, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (path), (mode)))
index 10a3733c14efc30a226b6495ca9af1eac69d3b90..320f9da3370d2384ba43dbb0caecfc5dce9ee772 100644 (file)
@@ -168,7 +168,7 @@ static int smbacl4_GetFileOwner(struct connection_struct *conn,
        memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
 
        /* Get the stat struct for the owner info. */
-       if (SMB_VFS_STAT(conn, filename, psbuf) != 0)
+       if (vfs_stat_smb_fname(conn, filename, psbuf) != 0)
        {
                DEBUG(8, ("SMB_VFS_STAT failed with error %s\n",
                        strerror(errno)));
index e0a5b14c67209b03422292d1cd88f6d41ae91d87..9f0b0b317a535727a0bd21dde3ea8731cc991e64 100644 (file)
@@ -196,9 +196,9 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
                if (fsp && fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf);
+                       ret = vfs_lstat_smb_fname(handle->conn, name, &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn, name, &sbuf);
+                       ret = vfs_stat_smb_fname(handle->conn, name, &sbuf);
                }
        }
 
@@ -288,9 +288,11 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
                if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name, &sbuf);
+                       ret = vfs_lstat_smb_fname(handle->conn, fsp->fsp_name,
+                                                 &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf);
+                       ret = vfs_stat_smb_fname(handle->conn, fsp->fsp_name,
+                                                &sbuf);
                }
        }
 
@@ -338,9 +340,9 @@ static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
                return NT_STATUS_INTERNAL_DB_CORRUPTION);
 
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf);
+               ret = vfs_lstat_smb_fname(handle->conn, fname, &sbuf);
        } else {
-               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+               ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
        }
 
        if (ret == -1) {
@@ -514,9 +516,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                } else {
                        if (fsp && fsp->posix_open) {
-                               ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
+                               ret = vfs_lstat_smb_fname(handle->conn,fname,
+                                                         &sbuf);
                        } else {
-                               ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                               ret = vfs_stat_smb_fname(handle->conn,fname,
+                                                        &sbuf);
                        }
                }
                if (ret == -1) {
@@ -621,9 +625,9 @@ static int unlink_acl_tdb(vfs_handle_struct *handle, const char *path)
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+               ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf);
        } else {
-               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+               ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
        }
 
        if (ret == -1) {
@@ -670,9 +674,9 @@ static int rmdir_acl_tdb(vfs_handle_struct *handle, const char *path)
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+               ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf);
        } else {
-               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+               ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
        }
 
        if (ret == -1) {
@@ -774,9 +778,13 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp,
                }
                if (fsp->is_directory || fsp->fh->fd == -1) {
                        if (fsp->posix_open) {
-                               ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+                               ret = vfs_lstat_smb_fname(fsp->conn,
+                                                         fsp->fsp_name,
+                                                         &sbuf);
                        } else {
-                               ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                               ret = vfs_stat_smb_fname(fsp->conn,
+                                                        fsp->fsp_name,
+                                                        &sbuf);
                        }
                } else {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
@@ -867,9 +875,9 @@ static int sys_acl_set_file_tdb(vfs_handle_struct *handle,
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+               ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf);
        } else {
-               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+               ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
        }
 
        if (ret == -1) {
@@ -904,9 +912,11 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle,
 
        if (fsp->is_directory || fsp->fh->fd == -1) {
                if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       ret = vfs_lstat_smb_fname(fsp->conn,fsp->fsp_name,
+                                                 &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       ret = vfs_stat_smb_fname(fsp->conn,fsp->fsp_name,
+                                                &sbuf);
                }
        } else {
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
index efcc87740a9142c87d57381aa8fa99572a5cc1c8..66bf21c4f73501797146f63c0b77b8b70ed449b1 100644 (file)
@@ -382,9 +382,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                } else {
                        if (fsp && fsp->posix_open) {
-                               ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
+                               ret = vfs_lstat_smb_fname(handle->conn, fname,
+                                                         &sbuf);
                        } else {
-                               ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                               ret = vfs_stat_smb_fname(handle->conn, fname,
+                                                        &sbuf);
                        }
                }
                if (ret == -1) {
@@ -574,9 +576,13 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
                }
                if (fsp->is_directory || fsp->fh->fd == -1) {
                        if (fsp->posix_open) {
-                               ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+                               ret = vfs_lstat_smb_fname(fsp->conn,
+                                                         fsp->fsp_name,
+                                                         &sbuf);
                        } else {
-                               ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                               ret = vfs_stat_smb_fname(fsp->conn,
+                                                        fsp->fsp_name,
+                                                        &sbuf);
                        }
                } else {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
index e537f01b039b484806815f4cb8bbf13e197e44a7..55371c60f5e767094483f09e0f768d6dfb2042c0 100644 (file)
@@ -662,7 +662,7 @@ static size_t afs_to_nt_acl(struct afs_acl *afs_acl,
        SMB_STRUCT_STAT sbuf;
 
        /* Get the stat struct for the owner info. */
-       if(SMB_VFS_STAT(conn, name, &sbuf) != 0) {
+       if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) {
                return 0;
        }
 
index 4525fa1da30c2a71e531f05310644b3c626adcd1..12a88750eef962facc621692ab7937080f5c85a4 100644 (file)
@@ -144,26 +144,52 @@ static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char
        return SMB_VFS_NEXT_RENAME(handle, capold, capnew);
 }
 
-static int cap_stat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
+static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       char *cappath = capencode(talloc_tos(), path);
+       char *cappath;
+       char *tmp_base_name = NULL;
+       int ret;
+
+       cappath = capencode(talloc_tos(), smb_fname->base_name);
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       return SMB_VFS_NEXT_STAT(handle, cappath, sbuf);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = cappath;
+
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(cappath);
+
+       return ret;
 }
 
-static int cap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
+static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
 {
-       char *cappath = capencode(talloc_tos(), path);
+       char *cappath;
+       char *tmp_base_name = NULL;
+       int ret;
+
+       cappath = capencode(talloc_tos(), smb_fname->base_name);
 
        if (!cappath) {
                errno = ENOMEM;
                return -1;
        }
-       return SMB_VFS_NEXT_LSTAT(handle, cappath, sbuf);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = cappath;
+
+       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(cappath);
+
+       return ret;
 }
 
 static int cap_unlink(vfs_handle_struct *handle, const char *path)
index 8d1c87a9fc66508e0aef4c5a2928da8d42762c19..c8c340d0a5e08d4d5044796f8d73d878fdd9693f 100644 (file)
@@ -177,27 +177,51 @@ static int catia_rename(vfs_handle_struct *handle,
 }
 
 static int catia_stat(vfs_handle_struct *handle,
-                     const char *fname, SMB_STRUCT_STAT *sbuf)
+                     struct smb_filename *smb_fname)
 {
-       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_STAT(handle, name, sbuf);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = name;
+
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(name);
+
+       return ret;
 }
 
 static int catia_lstat(vfs_handle_struct *handle,
-                      const char *path, SMB_STRUCT_STAT *sbuf)
+                      struct smb_filename *smb_fname)
 {
-       char *name = to_unix(talloc_tos(), path);
+       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_LSTAT(handle, name, sbuf);
+
+       tmp_base_name = smb_fname->base_name;
+       smb_fname->base_name = name;
+
+       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+
+       smb_fname->base_name = tmp_base_name;
+       TALLOC_FREE(name);
+
+       return ret;
 }
 
 static int catia_unlink(vfs_handle_struct *handle, const char *path)
index 0e7ba05632e50a4901dcafa885ada7743e44f20d..cd792aba3245c08d5cffa43259321934b1f23499 100644 (file)
@@ -549,12 +549,26 @@ static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
 #endif
 }
 
-static int vfswrap_stat(vfs_handle_struct *handle,  const char *fname, SMB_STRUCT_STAT *sbuf)
+static int vfswrap_stat(vfs_handle_struct *handle,
+                       struct smb_filename *smb_fname)
 {
        int result;
+       NTSTATUS status;
+       char *fname = NULL;
 
        START_PROFILE(syscall_stat);
-       result = sys_stat(fname, sbuf);
+
+       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_stat(fname, &smb_fname->st);
+
+       TALLOC_FREE(fname);
+
        END_PROFILE(syscall_stat);
        return result;
 }
@@ -569,12 +583,26 @@ static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUC
        return result;
 }
 
-int vfswrap_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf)
+static int vfswrap_lstat(vfs_handle_struct *handle,
+                        struct smb_filename *smb_fname)
 {
        int result;
+       NTSTATUS status;
+       char *fname = NULL;
 
        START_PROFILE(syscall_lstat);
-       result = sys_lstat(path, sbuf);
+
+       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_lstat(fname, &smb_fname->st);
+
+       TALLOC_FREE(fname);
+
        END_PROFILE(syscall_lstat);
        return result;
 }
@@ -1097,7 +1125,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        }
        else {
-               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+               ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
        }
 
        if (ret == -1) {
index cc3ab6220d0cb597cb6dbbcb83b1bce6904ee006..2740b612caa5b444f686f30a296c2835ecd56e3d 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
 
-static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
+static int fake_perms_stat(vfs_handle_struct *handle,
+                          struct smb_filename *smb_fname)
 {
        int ret = -1;
 
-       ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
        if (ret == 0) {
-               if (S_ISDIR(sbuf->st_ex_mode)) {
-                       sbuf->st_ex_mode = S_IFDIR | S_IRWXU;
+               if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+                       smb_fname->st.st_ex_mode = S_IFDIR | S_IRWXU;
                } else {
-                       sbuf->st_ex_mode = S_IRWXU;
+                       smb_fname->st.st_ex_mode = S_IRWXU;
                }
-               sbuf->st_ex_uid = handle->conn->server_info->utok.uid;
-               sbuf->st_ex_gid = handle->conn->server_info->utok.gid;
+               smb_fname->st.st_ex_uid = handle->conn->server_info->utok.uid;
+               smb_fname->st.st_ex_gid = handle->conn->server_info->utok.gid;
        }
 
        return ret;
index 5558b2f9b584a3c54c7548e7ad7194dd3e7818be..e47609d0a9a04a42a094b4b1b6510b05a0d1f78c 100644 (file)
@@ -151,11 +151,11 @@ static int smb_full_audit_rename(vfs_handle_struct *handle,
                        const char *oldname, const char *newname);
 static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp);
 static int smb_full_audit_stat(vfs_handle_struct *handle,
-                     const char *fname, SMB_STRUCT_STAT *sbuf);
+                              struct smb_filename *smb_fname);
 static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp,
                       SMB_STRUCT_STAT *sbuf);
 static int smb_full_audit_lstat(vfs_handle_struct *handle,
-                      const char *path, SMB_STRUCT_STAT *sbuf);
+                               struct smb_filename *smb_fname);
 static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle,
                       files_struct *fsp, const SMB_STRUCT_STAT *sbuf);
 static int smb_full_audit_unlink(vfs_handle_struct *handle,
@@ -1361,13 +1361,14 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp)
 }
 
 static int smb_full_audit_stat(vfs_handle_struct *handle,
-                     const char *fname, SMB_STRUCT_STAT *sbuf)
+                              struct smb_filename *smb_fname)
 {
        int result;
        
-       result = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       result = SMB_VFS_NEXT_STAT(handle, smb_fname);
 
-       do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", fname);
+       do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s",
+              smb_fname_str_dbg(smb_fname));
 
        return result;    
 }
@@ -1385,13 +1386,14 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp,
 }
 
 static int smb_full_audit_lstat(vfs_handle_struct *handle,
-                      const char *path, SMB_STRUCT_STAT *sbuf)
+                               struct smb_filename *smb_fname)
 {
        int result;
        
-       result = SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
+       result = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
 
-       do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", path);
+       do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s",
+              smb_fname_str_dbg(smb_fname));
 
        return result;    
 }
index 26f96889092f02468aa892c8d3045ae3da45b54f..47858cb3527d67da3cf35eebd3ea5794739e5182 100644 (file)
@@ -966,20 +966,28 @@ static size_t gpfs_get_xattr(struct vfs_handle_struct *handle,  const char *path
         return size;
 }
 
-static int vfs_gpfs_stat(struct vfs_handle_struct *handle, const char *fname,
-                        SMB_STRUCT_STAT *sbuf)
+static int vfs_gpfs_stat(struct vfs_handle_struct *handle,
+                        struct smb_filename *smb_fname)
 {
        struct gpfs_winattr attrs;
+       char *fname = NULL;
+       NTSTATUS status;
        int ret;
 
-       ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
        if (ret == -1) {
                return -1;
        }
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
        ret = get_gpfs_winattrs(CONST_DISCARD(char *, fname), &attrs);
+       TALLOC_FREE(fname);
        if (ret == 0) {
-               sbuf->st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
-               sbuf->st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
+               smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
+               smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
        }
        return 0;
 }
@@ -1005,20 +1013,28 @@ static int vfs_gpfs_fstat(struct vfs_handle_struct *handle,
        return 0;
 }
 
-static int vfs_gpfs_lstat(struct vfs_handle_struct *handle, const char *path,
-                         SMB_STRUCT_STAT *sbuf)
+static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
+                         struct smb_filename *smb_fname)
 {
        struct gpfs_winattr attrs;
+       char *path = NULL;
+       NTSTATUS status;
        int ret;
 
-       ret = SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
+       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        if (ret == -1) {
                return -1;
        }
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &path);
+       if (!NT_STATUS_IS_OK) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
        ret = get_gpfs_winattrs(CONST_DISCARD(char *, path), &attrs);
+       TALLOC_FREE(path);
        if (ret == 0) {
-               sbuf->st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
-               sbuf->st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
+               smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
+               smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
        }
        return 0;
 }
index 7d20a73d7bb24dbbee66df0d53be0c9fc48306ad..35341a5c3e3088ec07a5b6ddd3d8233c407958c9 100644 (file)
@@ -248,7 +248,7 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle,
         * that has _not_ been specified in "type" from the file first 
         * and concatenate it with the acl provided.
         */
-       if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
+       if (vfs_stat_smb_fname(handle->conn, name, &s) != 0) {
                DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
                goto done;
        }
index f1791aa6b17a4007bf999910ce8fbdc61141004e..f42fab72f7c43058d4f4b24dfded6ee6a7b7bb01 100644 (file)
@@ -214,7 +214,7 @@ static bool recycle_directory_exist(vfs_handle_struct *handle, const char *dname
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) {
+       if (vfs_stat_smb_fname(handle->conn, dname, &st) == 0) {
                if (S_ISDIR(st.st_ex_mode)) {
                        return True;
                }
@@ -227,7 +227,7 @@ static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname)
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) {
+       if (vfs_stat_smb_fname(handle->conn, fname, &st) == 0) {
                if (S_ISREG(st.st_ex_mode)) {
                        return True;
                }
@@ -246,7 +246,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn
 {
        SMB_STRUCT_STAT st;
 
-       if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
+       if (vfs_stat_smb_fname(handle->conn, fname, &st) != 0) {
                DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
                return (SMB_OFF_T)0;
        }
@@ -396,7 +396,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname,
 
        ZERO_STRUCT(ft);
 
-       if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
+       if (vfs_stat_smb_fname(handle->conn, fname, &st) != 0) {
                DEBUG(0,("recycle: stat for %s returned %s\n",
                         fname, strerror(errno)));
                return;
index 7b5b85d4beece91f8321583dc16ec0c5aeb150c3..03a8fd24ea8b23bbafae5ee1c10b549c1aadc387 100644 (file)
@@ -376,15 +376,19 @@ static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle,
 }
 
 static int shadow_copy2_stat(vfs_handle_struct *handle,
-                     const char *fname, SMB_STRUCT_STAT *sbuf)
+                            struct smb_filename *smb_fname)
 {
-        _SHADOW2_NEXT(STAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf));
+        _SHADOW2_NEXT_SMB_FNAME(STAT, (handle, smb_fname), int, -1,
+                               convert_sbuf(handle, smb_fname->base_name,
+                                            &smb_fname->st));
 }
 
 static int shadow_copy2_lstat(vfs_handle_struct *handle,
-                      const char *fname, SMB_STRUCT_STAT *sbuf)
+                             struct smb_filename *smb_fname)
 {
-        _SHADOW2_NEXT(LSTAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf));
+        _SHADOW2_NEXT_SMB_FNAME(LSTAT, (handle, smb_fname), int, -1,
+                               convert_sbuf(handle, smb_fname->base_name,
+                                            &smb_fname->st));
 }
 
 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
index fbfe664c6ed504f62e789567131beb83ded86aa4..dabb35c0c0f59c1395679767d8ca663809574c6f 100644 (file)
@@ -165,7 +165,7 @@ int solarisacl_sys_acl_set_file(vfs_handle_struct *handle,
         * that has not been specified in "type" from the file first 
         * and concatenate it with the acl provided.
         */
-       if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
+       if (vfs_stat_smb_fname(handle->conn, name, &s) != 0) {
                DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
                goto done;
        }
index 7d37af0181965eeecdebbdeb16afe58167fbb132..5f850174d873e521b3efa8ec1e9860a253a1ca85 100644 (file)
@@ -115,12 +115,18 @@ static bool mark_file_valid(vfs_handle_struct *handle, const char *path,
        return true;
 }
 
-static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
+/**
+ * Given an smb_filename, determine the stream directory using the file's
+ * base_name.
+ */
+static char *stream_dir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname,
                        const SMB_STRUCT_STAT *base_sbuf, bool create_it)
 {
        uint32_t hash;
+       struct smb_filename *smb_fname_hash = NULL;
        char *result = NULL;
-       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_STAT base_sbuf_tmp;
        uint8_t first, second;
        char *tmp;
        char *id_hex;
@@ -128,6 +134,7 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
        uint8 id_buf[16];
        bool check_valid;
        const char *rootdir;
+       NTSTATUS status;
 
        check_valid = lp_parm_bool(SNUM(handle->conn),
                      "streams_depot", "check_valid", true);
@@ -143,17 +150,29 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
                SNUM(handle->conn), "streams_depot", "directory",
                tmp);
 
+       /* Stat the base file if it hasn't already been done. */
        if (base_sbuf == NULL) {
-               if (SMB_VFS_NEXT_STAT(handle, base_path, &sbuf) == -1) {
-                       /*
-                        * base file is not there
-                        */
+               struct smb_filename *smb_fname_base = 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;
+               }
+               if (SMB_VFS_NEXT_STAT(handle, smb_fname_base) == -1) {
+                       TALLOC_FREE(smb_fname_base);
                        goto fail;
                }
-               base_sbuf = &sbuf;
+               base_sbuf_tmp = smb_fname_base->st;
+               TALLOC_FREE(smb_fname_base);
+       } else {
+               base_sbuf_tmp = *base_sbuf;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, base_sbuf);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &base_sbuf_tmp);
 
        push_file_id_16((char *)id_buf, &id);
 
@@ -179,15 +198,22 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
                return NULL;
        }
 
-       if (SMB_VFS_NEXT_STAT(handle, result, &sbuf) == 0) {
+       status = create_synthetic_smb_fname(talloc_tos(), result, NULL, NULL,
+                                           &smb_fname_hash);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto fail;
+       }
+
+       if (SMB_VFS_NEXT_STAT(handle, smb_fname_hash) == 0) {
                char *newname;
 
-               if (!S_ISDIR(sbuf.st_ex_mode)) {
+               if (!S_ISDIR(smb_fname_hash->st.st_ex_mode)) {
                        errno = EINVAL;
                        goto fail;
                }
 
-               if (file_is_valid(handle, base_path, check_valid)) {
+               if (file_is_valid(handle, smb_fname->base_name, check_valid)) {
                        return result;
                }
 
@@ -257,13 +283,15 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
                goto fail;
        }
 
-       if (!mark_file_valid(handle, base_path, check_valid)) {
+       if (!mark_file_valid(handle, smb_fname->base_name, check_valid)) {
                goto fail;
        }
 
+       TALLOC_FREE(smb_fname_hash);
        return result;
 
  fail:
+       TALLOC_FREE(smb_fname_hash);
        TALLOC_FREE(result);
        return NULL;
 }
@@ -282,7 +310,7 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle,
 
        *smb_fname_out = NULL;
 
-       dirname = stream_dir(handle, smb_fname->base_name, NULL, create_dir);
+       dirname = stream_dir(handle, smb_fname, NULL, create_dir);
 
        if (dirname == NULL) {
                status = map_nt_error_from_unix(errno);
@@ -315,10 +343,8 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle,
        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);
+       status = create_synthetic_smb_fname(talloc_tos(), stream_fname, NULL,
+                                           NULL, smb_fname_out);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -331,58 +357,47 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle,
        return status;
 }
 
+/*
+ * XXX: This function should be removed after the other vfs ops take
+ * smb_filename structs
+ */
 static char *stream_name(vfs_handle_struct *handle, const char *fname,
                         bool create_dir)
 {
-       char *base = NULL;
+       struct smb_filename *smb_fname = NULL;
+       struct smb_filename *smb_fname_stream = NULL;
        char *sname = NULL;
-       char *id_hex = NULL;
-       char *dirname, *stream_fname;
-
-       if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname,
-                                                   &base, &sname))) {
-               DEBUG(10, ("split_ntfs_stream_name failed\n"));
-               errno = ENOMEM;
-               goto fail;
-       }
+       NTSTATUS status;
 
-       /* if it's the ::$DATA stream just return the base file name */
-       if (!sname) {
-               return base;
+       status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+                                                 NULL, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
        }
 
-       dirname = stream_dir(handle, base, NULL, create_dir);
-
-       if (dirname == NULL) {
-               goto fail;
+       status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
+                                 create_dir);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
        }
 
-       stream_fname = talloc_asprintf(talloc_tos(), "%s/:%s", dirname, sname);
-
-       if (stream_fname == NULL) {
-               errno = ENOMEM;
-               goto fail;
+       status = get_full_smb_filename(talloc_tos(), smb_fname_stream,
+                                      &sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
        }
+ out:
+       TALLOC_FREE(smb_fname);
+       TALLOC_FREE(smb_fname_stream);
 
-       DEBUG(10, ("stream filename = %s\n", stream_fname));
-
-       TALLOC_FREE(base);
-       TALLOC_FREE(sname);
-       TALLOC_FREE(id_hex);
-
-       return stream_fname;
-
- fail:
-       DEBUG(5, ("stream_name failed: %s\n", strerror(errno)));
-       TALLOC_FREE(base);
-       TALLOC_FREE(sname);
-       TALLOC_FREE(id_hex);
-       return NULL;
+       return sname;
 }
 
 static NTSTATUS walk_streams(vfs_handle_struct *handle,
-                            const char *fname,
-                            const SMB_STRUCT_STAT *sbuf,
+                            struct smb_filename *smb_fname_base,
                             char **pdirname,
                             bool (*fn)(const char *dirname,
                                        const char *dirent,
@@ -393,7 +408,8 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
        SMB_STRUCT_DIR *dirhandle = NULL;
        char *dirent;
 
-       dirname = stream_dir(handle, fname, sbuf, false);
+       dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st,
+                            false);
 
        if (dirname == NULL) {
                if (errno == ENOENT) {
@@ -439,49 +455,99 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
-static int streams_depot_stat(vfs_handle_struct *handle, const char *fname,
-                             SMB_STRUCT_STAT *sbuf)
+/**
+ * Helper to stat/lstat the base file of an smb_fname. This will actually
+ * fills in the stat struct in smb_filename.
+ */
+static int streams_depot_stat_base(vfs_handle_struct *handle,
+                                  struct smb_filename *smb_fname,
+                                  bool follow_links)
 {
-       char *stream_fname;
+       char *tmp_stream_name;
+       int result;
+
+       tmp_stream_name = smb_fname->stream_name;
+       smb_fname->stream_name = NULL;
+       if (follow_links) {
+               result = SMB_VFS_NEXT_STAT(handle, smb_fname);
+       } else {
+               result = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+       }
+       smb_fname->stream_name = tmp_stream_name;
+       return result;
+}
+
+static int streams_depot_stat(vfs_handle_struct *handle,
+                             struct smb_filename *smb_fname)
+{
+       struct smb_filename *smb_fname_stream = NULL;
+       NTSTATUS status;
        int ret = -1;
 
-       DEBUG(10, ("streams_depot_stat called for [%s]\n", fname));
+       DEBUG(10, ("streams_depot_stat called for [%s]\n",
+                  smb_fname_str_dbg(smb_fname)));
 
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               return SMB_VFS_NEXT_STAT(handle, smb_fname);
        }
 
-       stream_fname = stream_name(handle, fname, false);
-       if (stream_fname == NULL) {
+       /* If the default stream is requested, just stat the base file. */
+       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
+               return streams_depot_stat_base(handle, smb_fname, true);
+       }
+
+       /* Stat the actual stream now. */
+       status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
+                                 false);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
                goto done;
        }
 
-       ret = SMB_VFS_NEXT_STAT(handle, stream_fname, sbuf);
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname_stream);
 
+       /* Update the original smb_fname with the stat info. */
+       smb_fname->st = smb_fname_stream->st;
  done:
-       TALLOC_FREE(stream_fname);
+       TALLOC_FREE(smb_fname_stream);
        return ret;
 }
 
-static int streams_depot_lstat(vfs_handle_struct *handle, const char *fname,
-                              SMB_STRUCT_STAT *sbuf)
+
+
+static int streams_depot_lstat(vfs_handle_struct *handle,
+                              struct smb_filename *smb_fname)
 {
-       char *stream_fname;
+       struct smb_filename *smb_fname_stream = NULL;
+       NTSTATUS status;
        int ret = -1;
 
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf);
+       DEBUG(10, ("streams_depot_lstat called for [%s]\n",
+                  smb_fname_str_dbg(smb_fname)));
+
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        }
 
-       stream_fname = stream_name(handle, fname, false);
-       if (stream_fname == NULL) {
+       /* If the default stream is requested, just stat the base file. */
+       if (is_ntfs_default_stream_smb_fname(smb_fname)) {
+               return streams_depot_stat_base(handle, smb_fname, false);
+       }
+
+       /* Stat the actual stream now. */
+       status = stream_smb_fname(handle, smb_fname, &smb_fname_stream,
+                                 false);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
                goto done;
        }
 
-       ret = SMB_VFS_NEXT_LSTAT(handle, stream_fname, sbuf);
+       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_stream);
 
  done:
-       TALLOC_FREE(stream_fname);
+       TALLOC_FREE(smb_fname_stream);
        return ret;
 }
 
@@ -490,7 +556,7 @@ static int streams_depot_open(vfs_handle_struct *handle,
                              files_struct *fsp, int flags, mode_t mode)
 {
        struct smb_filename *smb_fname_stream = NULL;
-       SMB_STRUCT_STAT base_sbuf;
+       struct smb_filename *smb_fname_base = NULL;
        NTSTATUS status;
        int ret = -1;
 
@@ -505,21 +571,29 @@ static int streams_depot_open(vfs_handle_struct *handle,
 
                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;
        }
 
        /* Ensure the base file still exists. */
-       ret = SMB_VFS_NEXT_STAT(handle, smb_fname->base_name, &base_sbuf);
+       status = create_synthetic_smb_fname(talloc_tos(),
+                                           smb_fname->base_name,
+                                           NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               errno = map_errno_from_nt_status(status);
+               goto done;
+       }
 
+       ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
        if (ret == -1) {
                goto done;
        }
 
+       /* Determine the stream name, and then open it. */
        status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true);
        if (!NT_STATUS_IS_OK(status)) {
                ret = -1;
@@ -531,13 +605,15 @@ static int streams_depot_open(vfs_handle_struct *handle,
 
  done:
        TALLOC_FREE(smb_fname_stream);
+       TALLOC_FREE(smb_fname_base);
        return ret;
 }
 
 static int streams_depot_unlink(vfs_handle_struct *handle,  const char *fname)
 {
+       struct smb_filename *smb_fname_base = NULL;
+       NTSTATUS status;
        int ret = -1;
-       SMB_STRUCT_STAT sbuf;
 
        DEBUG(10, ("streams_depot_unlink called for %s\n", fname));
 
@@ -559,18 +635,27 @@ static int streams_depot_unlink(vfs_handle_struct *handle,  const char *fname)
         * We potentially need to delete the per-inode streams directory
         */
 
+       status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf);
+               ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
        } else {
-               ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+               ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
        }
 
        if (ret == -1) {
+               TALLOC_FREE(smb_fname_base);
                return -1;
        }
 
-       if (sbuf.st_ex_nlink == 1) {
-               char *dirname = stream_dir(handle, fname, &sbuf, false);
+       if (smb_fname_base->st.st_ex_nlink == 1) {
+               char *dirname = stream_dir(handle, smb_fname_base,
+                                          &smb_fname_base->st, false);
 
                if (dirname != NULL) {
                        SMB_VFS_NEXT_RMDIR(handle, dirname);
@@ -578,6 +663,8 @@ static int streams_depot_unlink(vfs_handle_struct *handle,  const char *fname)
                TALLOC_FREE(dirname);
        }
 
+       TALLOC_FREE(smb_fname_base);
+
        return SMB_VFS_NEXT_UNLINK(handle, fname);
 }
 
@@ -699,32 +786,48 @@ static bool collect_one_stream(const char *dirname,
 {
        struct streaminfo_state *state =
                (struct streaminfo_state *)private_data;
-       char *full_sname;
-       SMB_STRUCT_STAT sbuf;
+       struct smb_filename *smb_fname = NULL;
+       char *sname = NULL;
+       NTSTATUS status;
+       bool ret;
 
-       if (asprintf(&full_sname, "%s/%s", dirname, dirent) == -1) {
+       sname = talloc_asprintf(talloc_tos(), "%s/%s", dirname, dirent);
+       if (sname == NULL) {
                state->status = NT_STATUS_NO_MEMORY;
-               return false;
+               ret = false;
+               goto out;
        }
-       if (SMB_VFS_NEXT_STAT(state->handle, full_sname, &sbuf) == -1) {
-               DEBUG(10, ("Could not stat %s: %s\n", full_sname,
-                          strerror(errno)));
-               SAFE_FREE(full_sname);
-               return true;
+
+       status = create_synthetic_smb_fname(talloc_tos(), sname, NULL,
+                                           NULL, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               state->status = status;
+               ret = false;
+               goto out;
        }
 
-       SAFE_FREE(full_sname);
+       if (SMB_VFS_NEXT_STAT(state->handle, smb_fname) == -1) {
+               DEBUG(10, ("Could not stat %s: %s\n", sname,
+                          strerror(errno)));
+               ret = true;
+               goto out;
+       }
 
        if (!add_one_stream(state->mem_ctx,
                            &state->num_streams, &state->streams,
-                           dirent, sbuf.st_ex_size,
+                           dirent, smb_fname->st.st_ex_size,
                            SMB_VFS_GET_ALLOC_SIZE(state->handle->conn, NULL,
-                                                  &sbuf))) {
+                                                  &smb_fname->st))) {
                state->status = NT_STATUS_NO_MEMORY;
-               return false;
+               ret = false;
+               goto out;
        }
 
-       return true;
+       ret = true;
+ out:
+       TALLOC_FREE(sname);
+       TALLOC_FREE(smb_fname);
+       return ret;
 }
 
 static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
@@ -734,42 +837,50 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
                                         unsigned int *pnum_streams,
                                         struct stream_struct **pstreams)
 {
-       SMB_STRUCT_STAT sbuf;
+       struct smb_filename *smb_fname_base = NULL;
        int ret;
        NTSTATUS status;
        struct streaminfo_state state;
 
+       status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        if ((fsp != NULL) && (fsp->fh->fd != -1)) {
                if (is_ntfs_stream_name(fsp->fsp_name)) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf);
+               ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &smb_fname_base->st);
        }
        else {
                if (is_ntfs_stream_name(fname)) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
                if (lp_posix_pathnames()) {
-                       ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf);
+                       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
                } else {
-                       ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+                       ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
                }
        }
 
        if (ret == -1) {
-               return map_nt_error_from_unix(errno);
+               status = map_nt_error_from_unix(errno);
+               goto out;
        }
 
        state.streams = NULL;
        state.num_streams = 0;
 
-       if (!S_ISDIR(sbuf.st_ex_mode)) {
+       if (!S_ISDIR(smb_fname_base->st.st_ex_mode)) {
                if (!add_one_stream(mem_ctx,
                                    &state.num_streams, &state.streams,
-                                   "::$DATA", sbuf.st_ex_size,
+                                   "::$DATA", smb_fname_base->st.st_ex_size,
                                    SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp,
-                                                          &sbuf))) {
-                       return NT_STATUS_NO_MEMORY;
+                                                      &smb_fname_base->st))) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto out;
                }
        }
 
@@ -777,22 +888,27 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
        state.handle = handle;
        state.status = NT_STATUS_OK;
 
-       status = walk_streams(handle, fname, &sbuf, NULL, collect_one_stream,
+       status = walk_streams(handle, smb_fname_base, NULL, collect_one_stream,
                              &state);
 
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(state.streams);
-               return status;
+               goto out;
        }
 
        if (!NT_STATUS_IS_OK(state.status)) {
                TALLOC_FREE(state.streams);
-               return state.status;
+               status = state.status;
+               goto out;
        }
 
        *pnum_streams = state.num_streams;
        *pstreams = state.streams;
-       return NT_STATUS_OK;
+       status = NT_STATUS_OK;
+
+ out:
+       TALLOC_FREE(smb_fname_base);
+       return status;
 }
 
 static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle)
index 715e1a7baf5df8a4181d91352cf2454f06884388..e87d60ec6040ef98380ec1d2def701b1b41da68c 100644 (file)
@@ -169,9 +169,32 @@ static bool streams_xattr_recheck(struct stream_io *sio)
        return true;
 }
 
+/**
+ * Helper to stat/lstat the base file of an smb_fname.
+ */
+static int streams_xattr_stat_base(vfs_handle_struct *handle,
+                                  struct smb_filename *smb_fname,
+                                  bool follow_links)
+{
+       char *tmp_stream_name;
+       int result;
+
+       tmp_stream_name = smb_fname->stream_name;
+       smb_fname->stream_name = NULL;
+       if (follow_links) {
+               result = SMB_VFS_NEXT_STAT(handle, smb_fname);
+       } else {
+               result = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+       }
+       smb_fname->stream_name = tmp_stream_name;
+       return result;
+}
+
 static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
                               SMB_STRUCT_STAT *sbuf)
 {
+       struct smb_filename *smb_fname_base = NULL;
+       NTSTATUS status;
        int ret = -1;
        struct stream_io *io = (struct stream_io *)
                VFS_FETCH_FSP_EXTENSION(handle, fsp);
@@ -186,11 +209,23 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
                return -1;
        }
 
+       /* Create an smb_filename with stream_name == NULL. */
+       status = create_synthetic_smb_fname(talloc_tos(),
+                                           io->base,
+                                           NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
        if (lp_posix_pathnames()) {
-               ret = SMB_VFS_LSTAT(handle->conn, io->base, sbuf);
+               ret = SMB_VFS_LSTAT(handle->conn, smb_fname_base);
        } else {
-               ret = SMB_VFS_STAT(handle->conn, io->base, sbuf);
+               ret = SMB_VFS_STAT(handle->conn, smb_fname_base);
        }
+       *sbuf = smb_fname_base->st;
+       TALLOC_FREE(smb_fname_base);
 
        if (ret == -1) {
                return -1;
@@ -212,105 +247,106 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
        return 0;
 }
 
-static int streams_xattr_stat(vfs_handle_struct *handle, const char *fname,
-                             SMB_STRUCT_STAT *sbuf)
+static int streams_xattr_stat(vfs_handle_struct *handle,
+                             struct smb_filename *smb_fname)
 {
        NTSTATUS status;
-       char *base = NULL, *sname = NULL;
        int result = -1;
-       char *xattr_name;
-
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_STAT(handle, fname, sbuf);
-       }
+       char *xattr_name = NULL;
 
-       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = EINVAL;
-               return -1;
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               return SMB_VFS_NEXT_STAT(handle, smb_fname);
        }
 
-       if (sname == NULL){
-               return SMB_VFS_NEXT_STAT(handle, base, sbuf);
+       /* 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);
        }
 
-       if (SMB_VFS_STAT(handle->conn, base, sbuf) == -1) {
-               goto fail;
+       /* Populate the stat struct with info from the base file. */
+       if (streams_xattr_stat_base(handle, smb_fname, true) == -1) {
+               return -1;
        }
 
-       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
-                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
-       if (xattr_name == NULL) {
-               errno = ENOMEM;
-               goto fail;
+       /* Derive the xattr name to lookup. */
+       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);
+               return -1;
        }
 
-       sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name);
-       if (sbuf->st_ex_size == -1) {
+       /* Augment the base file's stat information before returning. */
+       smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL,
+                                                 smb_fname->base_name,
+                                                 xattr_name);
+       if (smb_fname->st.st_ex_size == -1) {
                errno = ENOENT;
+               result = -1;
                goto fail;
        }
 
-       sbuf->st_ex_ino = stream_inode(sbuf, 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;
+       smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name);
+       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;
 
        result = 0;
  fail:
-       TALLOC_FREE(base);
-       TALLOC_FREE(sname);
+       TALLOC_FREE(xattr_name);
        return result;
 }
 
-static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname,
-                              SMB_STRUCT_STAT *sbuf)
+static int streams_xattr_lstat(vfs_handle_struct *handle,
+                              struct smb_filename *smb_fname)
 {
        NTSTATUS status;
-       char *base, *sname;
        int result = -1;
-       char *xattr_name;
-
-       if (!is_ntfs_stream_name(fname)) {
-               return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf);
-       }
+       char *xattr_name = NULL;
 
-       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = EINVAL;
-               goto fail;
+       if (!is_ntfs_stream_smb_fname(smb_fname)) {
+               return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        }
 
-       if (sname == NULL){
-               return SMB_VFS_NEXT_LSTAT(handle, base, sbuf);
+               /* 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);
        }
 
-       if (SMB_VFS_LSTAT(handle->conn, base, sbuf) == -1) {
-               goto fail;
+       /* Populate the stat struct with info from the base file. */
+       if (streams_xattr_stat_base(handle, smb_fname, false) == -1) {
+               return -1;
        }
 
-       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
-                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
-       if (xattr_name == NULL) {
-               errno = ENOMEM;
-               goto fail;
+       /* Derive the xattr name to lookup. */
+       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);
+               return -1;
        }
 
-       sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name);
-       if (sbuf->st_ex_size == -1) {
+       /* Augment the base file's stat information before returning. */
+       smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL,
+                                                 smb_fname->base_name,
+                                                 xattr_name);
+       if (smb_fname->st.st_ex_size == -1) {
                errno = ENOENT;
+               result = -1;
                goto fail;
        }
 
-       sbuf->st_ex_ino = stream_inode(sbuf, 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;
+       smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name);
+       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;
 
        result = 0;
+
  fail:
-       TALLOC_FREE(base);
-       TALLOC_FREE(sname);
+       TALLOC_FREE(xattr_name);
        return result;
 }
 
@@ -776,9 +812,9 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
                        return NT_STATUS_INVALID_PARAMETER;
                }
                if (lp_posix_pathnames()) {
-                       ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf);
+                       ret = vfs_lstat_smb_fname(handle->conn, fname, &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+                       ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
                }
        }
 
index 4e37ed6477bd0a1eed7171c5a45df52b1491b189..39adfdfe1581caf86016e07965f3c47462061fe9 100644 (file)
@@ -215,7 +215,7 @@ static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle,
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
@@ -337,7 +337,7 @@ static int xattr_tdb_setxattr(struct vfs_handle_struct *handle,
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
@@ -442,7 +442,7 @@ static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle,
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
@@ -542,7 +542,7 @@ static int xattr_tdb_removexattr(struct vfs_handle_struct *handle,
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
@@ -621,7 +621,7 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path)
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
@@ -660,7 +660,7 @@ static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
                return -1;
        }
 
index 760a2d520ccd543a2211af2643bb16595a792db9..ad21cf1d4007ad7821059b912cc39fc1112e54c8 100644 (file)
@@ -377,9 +377,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
           hasn't been renamed. */
 
        if (fsp->posix_open) {
-               ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+               ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
        } else {
-               ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+               ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
        }
 
        if (ret != 0) {
@@ -502,9 +502,11 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
                if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+                       ret = vfs_lstat_smb_fname(fsp->conn, fsp->fsp_name,
+                                                &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
+                       ret = vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
+                                                &sbuf);
                }
        }
 
index fb246cdf8c5755ce7e320e6142c8a45129f09556..aff30a6967cee7b4a694514bd26b26d091fb4cf8 100644 (file)
@@ -574,11 +574,13 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
                        long *poffset,
                        SMB_STRUCT_STAT *pst)
 {
+       struct smb_filename *smb_fname_base = NULL;
        char *name = NULL;
        char *pathreal = NULL;
        char *found_name = NULL;
        int ret;
        const char *name_temp = NULL;
+       NTSTATUS status;
 
        SET_STAT_INVALID(*pst);
 
@@ -624,10 +626,20 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
        if (!pathreal)
                return NULL;
 
-       if (SMB_VFS_STAT(dptr->conn, pathreal, pst) == 0) {
+       /* Create an smb_filename with stream_name == NULL. */
+       status = create_synthetic_smb_fname(ctx, pathreal, NULL, NULL,
+                                           &smb_fname_base);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NULL;
+       }
+
+       if (SMB_VFS_STAT(dptr->conn, smb_fname_base) == 0) {
+               *pst = smb_fname_base->st;
+               TALLOC_FREE(smb_fname_base);
                name = talloc_strdup(ctx, dptr->wcard);
                goto clean;
        } else {
+               TALLOC_FREE(smb_fname_base);
                /* If we get any other error than ENOENT or ENOTDIR
                   then the file exists we just can't stat it. */
                if (errno != ENOENT && errno != ENOTDIR) {
@@ -893,12 +905,32 @@ bool get_dir_entry(TALLOC_CTX *ctx,
                                return False;
                        }
 
-                       if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
-                               DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",
-                                       pathreal, strerror(errno) ));
-                               TALLOC_FREE(pathreal);
-                               TALLOC_FREE(filename);
-                               continue;
+                       if (!VALID_STAT(sbuf)) {
+                               struct smb_filename *smb_fname = NULL;
+                               NTSTATUS status;
+
+                               /* Create smb_fname with NULL stream_name. */
+                               status =
+                                   create_synthetic_smb_fname(ctx, pathreal,
+                                                              NULL, NULL,
+                                                              &smb_fname);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       TALLOC_FREE(pathreal);
+                                       TALLOC_FREE(filename);
+                                       return NULL;
+                               }
+
+                               if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
+                                       DEBUG(5,("Couldn't stat 1 [%s]. Error "
+                                                "= %s\n", pathreal,
+                                                strerror(errno)));
+                                       TALLOC_FREE(smb_fname);
+                                       TALLOC_FREE(pathreal);
+                                       TALLOC_FREE(filename);
+                                       continue;
+                               }
+                               sbuf = smb_fname->st;
+                               TALLOC_FREE(smb_fname);
                        }
 
                        *mode = dos_mode(conn,pathreal,&sbuf);
@@ -953,7 +985,8 @@ bool get_dir_entry(TALLOC_CTX *ctx,
  use it for anything security sensitive.
 ********************************************************************/
 
-static bool user_can_read_file(connection_struct *conn, char *name)
+static bool user_can_read_file(connection_struct *conn,
+                              struct smb_filename *smb_fname)
 {
        /*
         * If user is a member of the Admin group
@@ -964,7 +997,7 @@ static bool user_can_read_file(connection_struct *conn, char *name)
                return True;
        }
 
-       return can_access_file_acl(conn, name, FILE_READ_DATA);
+       return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
 }
 
 /*******************************************************************
@@ -1029,6 +1062,10 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
        bool hide_unreadable = lp_hideunreadable(SNUM(conn));
        bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
        bool hide_special = lp_hide_special_files(SNUM(conn));
+       char *entry = NULL;
+       struct smb_filename *smb_fname_base = NULL;
+       NTSTATUS status;
+       bool ret = false;
 
        if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
                return True; /* . and .. are always visible. */
@@ -1041,55 +1078,70 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
        }
 
        if (hide_unreadable || hide_unwriteable || hide_special) {
-               char *entry = NULL;
-
                entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
-               if (!entry)
-                       return false;
+               if (!entry) {
+                       ret = false;
+                       goto out;
                }
 
                /* If it's a dfs symlink, ignore _hide xxxx_ options */
                if (lp_host_msdfs() &&
                                lp_msdfs_root(SNUM(conn)) &&
                                is_msdfs_link(conn, entry, NULL)) {
-                       TALLOC_FREE(entry);
-                       return true;
+                       ret = true;
+                       goto out;
+               }
+
+               /* Create an smb_filename with stream_name == NULL. */
+               status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
+                                                   NULL, &smb_fname_base);
+               if (!NT_STATUS_IS_OK(status)) {
+                       ret = false;
+                       goto out;
                }
 
                /* If the file name does not exist, there's no point checking
                 * the configuration options. We succeed, on the basis that the
                 * checks *might* have passed if the file was present.
                 */
-               if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, entry, pst) != 0))
+               if (!VALID_STAT(*pst) &&
+                   (SMB_VFS_STAT(conn, smb_fname_base) != 0))
                {
-                       TALLOC_FREE(entry);
-                       return true;
+                       ret = true;
+                       goto out;
                }
 
+               *pst = smb_fname_base->st;
+
                /* Honour _hide unreadable_ option */
-               if (hide_unreadable && !user_can_read_file(conn, entry)) {
+               if (hide_unreadable &&
+                   !user_can_read_file(conn, smb_fname_base)) {
                        DEBUG(10,("is_visible_file: file %s is unreadable.\n",
                                 entry ));
-                       TALLOC_FREE(entry);
-                       return false;
+                       ret = false;
+                       goto out;
                }
                /* Honour _hide unwriteable_ option */
                if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
                        DEBUG(10,("is_visible_file: file %s is unwritable.\n",
                                 entry ));
-                       TALLOC_FREE(entry);
-                       return false;
+                       ret = false;
+                       goto out;
                }
                /* Honour _hide_special_ option */
                if (hide_special && file_is_special(conn, entry, pst)) {
                        DEBUG(10,("is_visible_file: file %s is special.\n",
                                 entry ));
-                       TALLOC_FREE(entry);
-                       return false;
+                       ret = false;
+                       goto out;
                }
-               TALLOC_FREE(entry);
        }
-       return true;
+
+       ret = true;
+ out:
+       TALLOC_FREE(smb_fname_base);
+       TALLOC_FREE(entry);
+       return ret;
 }
 
 static int smb_Dir_destructor(struct smb_Dir *dirp)
index 8149eea7f59ad8726ac20c40fea9d55269723046..afebb9efd0e2efa933a8e0e20762bd4867118b8b 100644 (file)
@@ -81,7 +81,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
 
                DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
                          inherit_from_dir));
-               if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
+               if (vfs_stat_smb_fname(conn, inherit_from_dir, &sbuf) != 0) {
                        DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
                                 inherit_from_dir, strerror(errno)));
                        return(0);      /* *** shouldn't happen! *** */
@@ -560,7 +560,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        }
 
        if (!VALID_STAT(*st)) {
-               if (SMB_VFS_STAT(conn,fname,st))
+               if (vfs_stat_smb_fname(conn,fname,st))
                        return(-1);
        }
 
index 195f722471d13409f57b8cf849b97b7978e3019d..87d45c5e7f6aabc900cb417e7006ca1ad7fd863f 100644 (file)
  * Security descriptor / NT Token level access check function.
  */
 bool can_access_file_acl(struct connection_struct *conn,
-                               const char * fname,
-                               uint32_t access_mask)
+                        const struct smb_filename *smb_fname,
+                        uint32_t access_mask)
 {
        NTSTATUS status;
        uint32_t access_granted;
        struct security_descriptor *secdesc = NULL;
+       char *fname = NULL;
+       bool ret;
 
        if (conn->server_info->utok.uid == 0 || conn->admin_user) {
                /* I'm sorry sir, I didn't know you were root... */
                return true;
        }
 
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = false;
+               goto out;
+       }
+
        status = SMB_VFS_GET_NT_ACL(conn, fname,
                                    (OWNER_SECURITY_INFORMATION |
                                     GROUP_SECURITY_INFORMATION |
@@ -46,13 +54,17 @@ bool can_access_file_acl(struct connection_struct *conn,
                                    &secdesc);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
-               return false;
+               ret = false;
+               goto out;
        }
 
        status = se_access_check(secdesc, conn->server_info->ptok,
                                 access_mask, &access_granted);
+       ret = NT_STATUS_IS_OK(status);
+ out:
+       TALLOC_FREE(fname);
        TALLOC_FREE(secdesc);
-       return NT_STATUS_IS_OK(status);
+       return ret;
 }
 
 /****************************************************************************
@@ -61,11 +73,13 @@ bool can_access_file_acl(struct connection_struct *conn,
 ****************************************************************************/
 
 bool can_delete_file_in_directory(connection_struct *conn,
-                                 const struct smb_filename *smb_fname)
+                                 struct smb_filename *smb_fname)
 {
-       SMB_STRUCT_STAT sbuf;
        TALLOC_CTX *ctx = talloc_tos();
        char *dname = NULL;
+       struct smb_filename *smb_fname_parent = NULL;
+       NTSTATUS status;
+       bool ret;
 
        if (!CAN_WRITE(conn)) {
                return False;
@@ -75,47 +89,49 @@ bool can_delete_file_in_directory(connection_struct *conn,
        if (!parent_dirname(ctx, smb_fname->base_name, &dname, NULL)) {
                return False;
        }
-       if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
-               return False;
+
+       status = create_synthetic_smb_fname(ctx, dname, NULL, NULL,
+                                           &smb_fname_parent);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = false;
+               goto out;
+       }
+
+       if(SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
+               ret = false;
+               goto out;
        }
 
        /* fast paths first */
 
-       if (!S_ISDIR(sbuf.st_ex_mode)) {
-               return False;
+       if (!S_ISDIR(smb_fname_parent->st.st_ex_mode)) {
+               ret = false;
+               goto out;
        }
        if (conn->server_info->utok.uid == 0 || conn->admin_user) {
                /* I'm sorry sir, I didn't know you were root... */
-               return True;
+               ret = true;
+               goto out;
        }
 
 #ifdef S_ISVTX
        /* sticky bit means delete only by owner of file or by root or
         * by owner of directory. */
-       if (sbuf.st_ex_mode & S_ISVTX) {
-               SMB_STRUCT_STAT sbuf_file;
-               char *fname = NULL;
-               NTSTATUS status;
-
-               status = get_full_smb_filename(talloc_tos(), smb_fname,
-                                              &fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return false;
-               }
-               if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
-                       TALLOC_FREE(fname);
+       if (smb_fname_parent->st.st_ex_mode & S_ISVTX) {
+               if(SMB_VFS_STAT(conn, smb_fname) != 0) {
                        if (errno == ENOENT) {
                                /* If the file doesn't already exist then
                                 * yes we'll be able to delete it. */
-                               return True;
+                               ret = true;
+                               goto out;
                        }
                        DEBUG(10,("can_delete_file_in_directory: can't "
                                  "stat file %s (%s)",
                                  smb_fname_str_dbg(smb_fname),
                                  strerror(errno) ));
-                       return False;
+                       ret = false;
+                       goto out;
                }
-               TALLOC_FREE(fname);
 
                /*
                 * Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
@@ -125,12 +141,15 @@ bool can_delete_file_in_directory(connection_struct *conn,
                 * or the owner of the directory as we have no possible
                 * chance of deleting. Otherwise, go on and check the ACL.
                 */
-               if ((conn->server_info->utok.uid != sbuf.st_ex_uid) &&
-                               (conn->server_info->utok.uid != sbuf_file.st_ex_uid)) {
+               if ((conn->server_info->utok.uid !=
+                       smb_fname_parent->st.st_ex_uid) &&
+                   (conn->server_info->utok.uid != smb_fname->st.st_ex_uid)) {
                        DEBUG(10,("can_delete_file_in_directory: not "
                                  "owner of file %s or directory %s",
-                                 smb_fname_str_dbg(smb_fname), dname));
-                       return False;
+                                 smb_fname_str_dbg(smb_fname),
+                                 smb_fname_str_dbg(smb_fname_parent)));
+                       ret = false;
+                       goto out;
                }
        }
 #endif
@@ -146,7 +165,11 @@ bool can_delete_file_in_directory(connection_struct *conn,
         * check the file DELETE permission separately.
         */
 
-       return can_access_file_acl(conn, dname, FILE_DELETE_CHILD);
+       ret = can_access_file_acl(conn, smb_fname_parent, FILE_DELETE_CHILD);
+ out:
+       TALLOC_FREE(dname);
+       TALLOC_FREE(smb_fname_parent);
+       return ret;
 }
 
 /****************************************************************************
@@ -155,7 +178,9 @@ bool can_delete_file_in_directory(connection_struct *conn,
  Note this doesn't take into account share write permissions.
 ****************************************************************************/
 
-bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint32 access_mask)
+bool can_access_file_data(connection_struct *conn,
+                         const struct smb_filename *smb_fname,
+                         uint32 access_mask)
 {
        if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
                return False;
@@ -165,27 +190,31 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
        /* some fast paths first */
 
        DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n",
-               (unsigned int)access_mask, fname ));
+                 (unsigned int)access_mask, smb_fname_str_dbg(smb_fname)));
 
        if (conn->server_info->utok.uid == 0 || conn->admin_user) {
                /* I'm sorry sir, I didn't know you were root... */
                return True;
        }
 
-       SMB_ASSERT(psbuf && VALID_STAT(*psbuf));
+       SMB_ASSERT(VALID_STAT(smb_fname->st));
 
        /* Check primary owner access. */
-       if (conn->server_info->utok.uid == psbuf->st_ex_uid) {
+       if (conn->server_info->utok.uid == smb_fname->st.st_ex_uid) {
                switch (access_mask) {
                        case FILE_READ_DATA:
-                               return (psbuf->st_ex_mode & S_IRUSR) ? True : False;
+                               return (smb_fname->st.st_ex_mode & S_IRUSR) ?
+                                   True : False;
 
                        case FILE_WRITE_DATA:
-                               return (psbuf->st_ex_mode & S_IWUSR) ? True : False;
+                               return (smb_fname->st.st_ex_mode & S_IWUSR) ?
+                                   True : False;
 
                        default: /* FILE_READ_DATA|FILE_WRITE_DATA */
 
-                               if ((psbuf->st_ex_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
+                               if ((smb_fname->st.st_ex_mode &
+                                       (S_IWUSR|S_IRUSR)) ==
+                                   (S_IWUSR|S_IRUSR)) {
                                        return True;
                                } else {
                                        return False;
@@ -195,7 +224,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
 
        /* now for ACL checks */
 
-       return can_access_file_acl(conn, fname, access_mask);
+       return can_access_file_acl(conn, smb_fname, access_mask);
 }
 
 /****************************************************************************
@@ -205,7 +234,21 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
 
 bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf)
 {
-       return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA);
+       struct smb_filename *smb_fname;
+       NTSTATUS status;
+       bool ret;
+
+       status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       ret = can_access_file_data(conn, smb_fname, FILE_WRITE_DATA);
+
+       TALLOC_FREE(smb_fname);
+
+       return ret;
 }
 
 /****************************************************************************
index de5f83c868f372e544998057731ad72da87ca319..843b3f9586a8df735bf3353955ab8fcd5f1a3437 100644 (file)
@@ -949,7 +949,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug
 int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst)
 {
        if (fsp->fh->fd == -1) {
-               return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst);
+               return vfs_stat_smb_fname(fsp->conn, fsp->fsp_name, pst);
        } else {
                return SMB_VFS_FSTAT(fsp, pst);
        }
index 9854407a701d945a6f9aa26894e00c4817530867..bf12e86d53c58b7fd7e2dae05da03da732a3000e 100644 (file)
@@ -110,7 +110,7 @@ NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_f
  */
 NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
                                    const char *stream_name,
-                                   SMB_STRUCT_STAT *psbuf,
+                                   const SMB_STRUCT_STAT *psbuf,
                                    struct smb_filename **smb_fname_out)
 {
        struct smb_filename smb_fname_loc;
@@ -135,15 +135,18 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
  */
 NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
                                          const char *fname,
-                                         SMB_STRUCT_STAT *psbuf,
+                                         const SMB_STRUCT_STAT *psbuf,
                                          struct smb_filename **smb_fname_out)
 {
        NTSTATUS status;
        const char *stream_name = NULL;
        char *base_name = NULL;
 
+       if (!lp_posix_pathnames()) {
+               stream_name = strchr_m(fname, ':');
+       }
+
        /* Setup the base_name/stream_name. */
-       stream_name = strchr_m(fname, ':');
        if (stream_name) {
                base_name = talloc_strndup(ctx, fname,
                                           PTR_DIFF(stream_name, fname));
@@ -161,6 +164,60 @@ NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
        return status;
 }
 
+/**
+ * XXX: This is temporary and there should be no callers of this once
+ * smb_filename is plumbed through all path based operations.
+ */
+int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
+                      SMB_STRUCT_STAT *psbuf)
+{
+       struct smb_filename *smb_fname = NULL;
+       NTSTATUS status;
+       int ret;
+
+       status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
+       ret = SMB_VFS_STAT(conn, smb_fname);
+       if (ret != -1) {
+               *psbuf = smb_fname->st;
+       }
+
+       TALLOC_FREE(smb_fname);
+       return ret;
+}
+
+/**
+ * XXX: This is temporary and there should be no callers of this once
+ * smb_filename is plumbed through all path based operations.
+ */
+int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
+                       SMB_STRUCT_STAT *psbuf)
+{
+       struct smb_filename *smb_fname = NULL;
+       NTSTATUS status;
+       int ret;
+
+       status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
+       ret = SMB_VFS_LSTAT(conn, smb_fname);
+       if (ret != -1) {
+               *psbuf = smb_fname->st;
+       }
+
+       TALLOC_FREE(smb_fname);
+       return ret;
+}
+
 /**
  * Return a string using the debug_ctx()
  */
@@ -315,7 +372,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                if (!(name = talloc_strdup(ctx,"."))) {
                        return NT_STATUS_NO_MEMORY;
                }
-               if (SMB_VFS_STAT(conn,name,&st) == 0) {
+               if (vfs_stat_smb_fname(conn,name,&st) == 0) {
                        smb_fname->st = st;
                } else {
                        return map_nt_error_from_unix(errno);
@@ -417,9 +474,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
         */
 
        if (posix_pathnames) {
-               ret = SMB_VFS_LSTAT(conn,name,&st);
+               ret = vfs_lstat_smb_fname(conn,name,&st);
        } else {
-               ret = SMB_VFS_STAT(conn,name,&st);
+               ret = vfs_stat_smb_fname(conn,name,&st);
        }
 
        if (ret == 0) {
@@ -535,9 +592,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                 */
 
                if (posix_pathnames) {
-                       ret = SMB_VFS_LSTAT(conn,name, &st);
+                       ret = vfs_lstat_smb_fname(conn,name, &st);
                } else {
-                       ret = SMB_VFS_STAT(conn,name, &st);
+                       ret = vfs_stat_smb_fname(conn,name, &st);
                }
 
                if (ret == 0) {
@@ -764,9 +821,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                                 */
 
                                if (posix_pathnames) {
-                                       ret = SMB_VFS_LSTAT(conn,name, &st);
+                                       ret = vfs_lstat_smb_fname(conn,name,
+                                                                 &st);
                                } else {
-                                       ret = SMB_VFS_STAT(conn,name, &st);
+                                       ret = vfs_stat_smb_fname(conn,name,
+                                                                &st);
                                }
 
                                if (ret == 0) {
@@ -1073,17 +1132,11 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
                                  const char *orig_path,
                                  struct smb_filename *smb_fname)
 {
-       char *result = NULL;
        NTSTATUS status;
        unsigned int i, num_streams;
        struct stream_struct *streams = NULL;
 
-       status = get_full_smb_filename(mem_ctx, smb_fname, &result);
-       if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
+       if (SMB_VFS_STAT(conn, smb_fname) == 0) {
                return NT_STATUS_OK;
        }
 
@@ -1132,24 +1185,22 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
        TALLOC_FREE(smb_fname->stream_name);
        smb_fname->stream_name = talloc_strdup(mem_ctx, streams[i].name);
 
-       TALLOC_FREE(result);
-       status = get_full_smb_filename(mem_ctx, smb_fname, &result);
-       if (!NT_STATUS_IS_OK(status)) {
-               status = NT_STATUS_NO_MEMORY;
-               goto fail;
-       }
-
        SET_STAT_INVALID(smb_fname->st);
 
-       if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
-               stat_cache_add(orig_path, result, conn->case_sensitive);
-       }
+       if (SMB_VFS_STAT(conn, smb_fname) == 0) {
+               char *result = NULL;
 
-       TALLOC_FREE(streams);
-       return NT_STATUS_OK;
+               status = get_full_smb_filename(mem_ctx, smb_fname, &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto fail;
+               }
 
+               stat_cache_add(orig_path, result, conn->case_sensitive);
+               TALLOC_FREE(result);
+       }
+       status = NT_STATUS_OK;
  fail:
-       TALLOC_FREE(result);
        TALLOC_FREE(streams);
        return status;
 }
index e2f31f077c4eef5ea0b374a9e24e1e6df6f0086b..e6f877cfbb1b7b1409f9ef26fdc18c11addececf 100644 (file)
@@ -437,7 +437,7 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
                sbufp = &st;
        }
 
-       if (SMB_VFS_LSTAT(conn, path, sbufp) != 0) {
+       if (vfs_lstat_smb_fname(conn, path, sbufp) != 0) {
                DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n",
                        path));
                goto err;
index 12a75cc9f6363d83dadc444e489d2a2336c70492..a242fc3ac03d3517cc28c6108347769d86740285 100644 (file)
@@ -341,25 +341,35 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
        char *fullpath;
        char *parent;
        const char *name;
-       SMB_STRUCT_STAT sbuf;
 
        if (path[0] == '.' && path[1] == '/') {
                path += 2;
        }
-       if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
-               DEBUG(0, ("asprintf failed\n"));
-               return;
+       if (parent_dirname(talloc_tos(), path, &parent, &name)) {
+               struct smb_filename *smb_fname_parent = NULL;
+               NTSTATUS status;
+
+               status = create_synthetic_smb_fname(talloc_tos(), parent, NULL,
+                                                   NULL, &smb_fname_parent);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return;
+               }
+               if (SMB_VFS_STAT(conn, smb_fname_parent) != -1) {
+                       notify_onelevel(conn->notify_ctx, action, filter,
+                           SMB_VFS_FILE_ID_CREATE(conn, &smb_fname_parent->st),
+                           name);
+               }
+               TALLOC_FREE(smb_fname_parent);
        }
 
-       if (parent_dirname(talloc_tos(), path, &parent, &name)
-           && (SMB_VFS_STAT(conn, parent, &sbuf) != -1)) {
-               notify_onelevel(conn->notify_ctx, action, filter,
-                               SMB_VFS_FILE_ID_CREATE(conn, &sbuf),
-                               name);
+       fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
+                                  path);
+       if (fullpath == NULL) {
+               DEBUG(0, ("asprintf failed\n"));
+               return;
        }
-
        notify_trigger(conn->notify_ctx, action, filter, fullpath);
-       SAFE_FREE(fullpath);
+       TALLOC_FREE(fullpath);
 }
 
 static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
index 72370c8c7c7d96654d45664306e7ae2e613d6785..5b62ff022dd8e909c37ccad13f081503fb7d11e1 100644 (file)
@@ -193,31 +193,41 @@ void change_file_owner_to_parent(connection_struct *conn,
                                        const char *inherit_from_dir,
                                        files_struct *fsp)
 {
-       SMB_STRUCT_STAT parent_st;
+       struct smb_filename *smb_fname_parent = NULL;
+       NTSTATUS status;
        int ret;
 
-       ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+       status = create_synthetic_smb_fname(talloc_tos(), inherit_from_dir,
+                                           NULL, NULL, &smb_fname_parent);
+       if (!NT_STATUS_IS_OK(status)) {
+               return;
+       }
+
+       ret = SMB_VFS_STAT(conn, smb_fname_parent);
        if (ret == -1) {
                DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
                         "directory %s. Error was %s\n",
-                        inherit_from_dir, strerror(errno) ));
+                        smb_fname_str_dbg(smb_fname_parent),
+                        strerror(errno)));
                return;
        }
 
        become_root();
-       ret = SMB_VFS_FCHOWN(fsp, parent_st.st_ex_uid, (gid_t)-1);
+       ret = SMB_VFS_FCHOWN(fsp, smb_fname_parent->st.st_ex_uid, (gid_t)-1);
        unbecome_root();
        if (ret == -1) {
                DEBUG(0,("change_file_owner_to_parent: failed to fchown "
                         "file %s to parent directory uid %u. Error "
                         "was %s\n", fsp->fsp_name,
-                        (unsigned int)parent_st.st_ex_uid,
+                        (unsigned int)smb_fname_parent->st.st_ex_uid,
                         strerror(errno) ));
        }
 
        DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
                  "parent directory uid %u.\n", fsp->fsp_name,
-                 (unsigned int)parent_st.st_ex_uid ));
+                 (unsigned int)smb_fname_parent->st.st_ex_uid));
+
+       TALLOC_FREE(smb_fname_parent);
 }
 
 NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
@@ -225,20 +235,27 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                                       const char *fname,
                                       SMB_STRUCT_STAT *psbuf)
 {
+       struct smb_filename *smb_fname_parent = NULL;
+       struct smb_filename *smb_fname_cwd = NULL;
        char *saved_dir = NULL;
-       SMB_STRUCT_STAT sbuf;
-       SMB_STRUCT_STAT parent_st;
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
        int ret;
 
-       ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+       status = create_synthetic_smb_fname(ctx, inherit_from_dir, NULL, NULL,
+                                           &smb_fname_parent);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       ret = SMB_VFS_STAT(conn, smb_fname_parent);
        if (ret == -1) {
                status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
                         "directory %s. Error was %s\n",
-                        inherit_from_dir, strerror(errno) ));
-               return status;
+                        smb_fname_str_dbg(smb_fname_parent),
+                        strerror(errno)));
+               goto out;
        }
 
        /* We've already done an lstat into psbuf, and we know it's a
@@ -254,7 +271,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                DEBUG(0,("change_dir_owner_to_parent: failed to get "
                         "current working directory. Error was %s\n",
                         strerror(errno)));
-               return status;
+               goto out;
        }
 
        /* Chdir into the new path. */
@@ -263,47 +280,58 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                DEBUG(0,("change_dir_owner_to_parent: failed to change "
                         "current working directory to %s. Error "
                         "was %s\n", fname, strerror(errno) ));
-               goto out;
+               goto chdir;
+       }
+
+       status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
+                                           &smb_fname_cwd);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+       ret = SMB_VFS_STAT(conn, smb_fname_cwd);
+       if (ret == -1) {
                status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat "
                         "directory '.' (%s) Error was %s\n",
                         fname, strerror(errno)));
-               goto out;
+               goto chdir;
        }
 
        /* Ensure we're pointing at the same place. */
-       if (sbuf.st_ex_dev != psbuf->st_ex_dev ||
-           sbuf.st_ex_ino != psbuf->st_ex_ino ||
-           sbuf.st_ex_mode != psbuf->st_ex_mode ) {
+       if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev ||
+           smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino ||
+           smb_fname_cwd->st.st_ex_mode != psbuf->st_ex_mode ) {
                DEBUG(0,("change_dir_owner_to_parent: "
                         "device/inode/mode on directory %s changed. "
                         "Refusing to chown !\n", fname ));
                status = NT_STATUS_ACCESS_DENIED;
-               goto out;
+               goto chdir;
        }
 
        become_root();
-       ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_ex_uid, (gid_t)-1);
+       ret = SMB_VFS_CHOWN(conn, ".", smb_fname_parent->st.st_ex_uid,
+                           (gid_t)-1);
        unbecome_root();
        if (ret == -1) {
                status = map_nt_error_from_unix(errno);
                DEBUG(10,("change_dir_owner_to_parent: failed to chown "
                          "directory %s to parent directory uid %u. "
                          "Error was %s\n", fname,
-                         (unsigned int)parent_st.st_ex_uid, strerror(errno) ));
-               goto out;
+                         (unsigned int)smb_fname_parent->st.st_ex_uid,
+                         strerror(errno) ));
+               goto chdir;
        }
 
        DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
                  "directory %s to parent directory uid %u.\n",
-                 fname, (unsigned int)parent_st.st_ex_uid ));
-
- out:
+                 fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
 
+ chdir:
        vfs_ChDir(conn,saved_dir);
+ out:
+       TALLOC_FREE(smb_fname_parent);
+       TALLOC_FREE(smb_fname_cwd);
        return status;
 }
 
@@ -537,7 +565,7 @@ static NTSTATUS open_file(files_struct *fsp,
                int ret;
 
                if (fsp->fh->fd == -1) {
-                       ret = SMB_VFS_STAT(conn, path, &smb_fname->st);
+                       ret = SMB_VFS_STAT(conn, smb_fname);
                } else {
                        ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
                        /* If we have an fd, this stat should succeed. */
@@ -1857,8 +1885,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                                can_access_mask = FILE_READ_DATA;
                        }
 
-                       if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
-                           !can_access_file_data(conn, fname, &smb_fname->st, can_access_mask)) {
+                       if (((can_access_mask & FILE_WRITE_DATA) &&
+                               !CAN_WRITE(conn)) ||
+                           !can_access_file_data(conn, smb_fname,
+                                                 can_access_mask)) {
                                can_access = False;
                        }
 
@@ -2347,7 +2377,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        /* Ensure we're checking for a symlink here.... */
        /* We don't want to get caught by a symlink racer. */
 
-       if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
+       if (vfs_lstat_smb_fname(conn, name, psbuf) == -1) {
                DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
                          name, strerror(errno)));
                return map_nt_error_from_unix(errno);
@@ -2471,7 +2501,7 @@ static NTSTATUS open_directory(connection_struct *conn,
                         * We want to follow symlinks here.
                         */
 
-                       if (SMB_VFS_STAT(conn, fname, &smb_dname->st) != 0) {
+                       if (SMB_VFS_STAT(conn, smb_dname) != 0) {
                                return map_nt_error_from_unix(errno);
                        }
                                
@@ -2836,34 +2866,24 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
 
        for (i=0; i<num_streams; i++) {
                struct smb_filename *smb_fname = NULL;
-               char *streamname = NULL;
-               SMB_STRUCT_STAT sbuf;
 
                if (strequal(stream_info[i].name, "::$DATA")) {
                        streams[i] = NULL;
                        continue;
                }
 
-               streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
-                                            stream_info[i].name);
-               if (streamname == NULL) {
-                       DEBUG(0, ("talloc_aprintf failed\n"));
-                       status = NT_STATUS_NO_MEMORY;
-               }
-
-               if (SMB_VFS_STAT(conn, streamname, &sbuf) == -1) {
-                       SET_STAT_INVALID(sbuf);
-               }
-
-               TALLOC_FREE(streamname);
-
                status = create_synthetic_smb_fname(talloc_tos(), fname,
                                                    stream_info[i].name,
-                                                   &sbuf, &smb_fname);
+                                                   NULL, &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        goto fail;
                }
 
+               if (SMB_VFS_STAT(conn, smb_fname) == -1) {
+                       DEBUG(10, ("Unable to stat stream: %s\n",
+                                  smb_fname_str_dbg(smb_fname)));
+               }
+
                status = SMB_VFS_CREATE_FILE(
                         conn,                  /* conn */
                         NULL,                  /* req */
@@ -2999,7 +3019,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
            && (share_access & FILE_SHARE_DELETE)
            && (access_mask & DELETE_ACCESS)
            && (!(can_delete_file_in_directory(conn, smb_fname) ||
-                can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
+                can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) {
                status = NT_STATUS_ACCESS_DENIED;
                DEBUG(10,("create_file_unixpath: open file %s "
                          "for delete ACCESS_DENIED\n",
@@ -3036,7 +3056,6 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
            && (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) {
                uint32 base_create_disposition;
                struct smb_filename *smb_fname_base = NULL;
-               SMB_STRUCT_STAT sbuf;
 
                if (create_options & FILE_DIRECTORY_FILE) {
                        status = NT_STATUS_NOT_A_DIRECTORY;
@@ -3052,19 +3071,20 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
                        break;
                }
 
-               if (SMB_VFS_STAT(conn, smb_fname->base_name, &sbuf) == -1) {
-                       SET_STAT_INVALID(sbuf);
-               }
-
                /* Create an smb_filename with stream_name == NULL. */
                status = create_synthetic_smb_fname(talloc_tos(),
                                                    smb_fname->base_name,
-                                                   NULL, &sbuf,
+                                                   NULL, NULL,
                                                    &smb_fname_base);
                if (!NT_STATUS_IS_OK(status)) {
                        goto fail;
                }
 
+               if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
+                       DEBUG(10, ("Unable to stat stream: %s\n",
+                                  smb_fname_str_dbg(smb_fname_base)));
+               }
+
                /* Open the base file. */
                status = create_file_unixpath(conn, NULL, smb_fname_base, 0,
                                              FILE_SHARE_READ
index bdd27fb794d29db94820ac19ebcffa6756a4f2db..437112c751d5cc6916c0e19e0f7e4162326db55b 100644 (file)
@@ -3351,7 +3351,7 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
        DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
 
        /* Get the stat struct for the owner info. */
-       if(SMB_VFS_STAT(conn, name, &sbuf) != 0) {
+       if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
@@ -3432,7 +3432,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
                return -1;
        }
 
-       if (SMB_VFS_STAT(conn,fname,&st)) {
+       if (vfs_stat_smb_fname(conn,fname,&st)) {
                return -1;
        }
 
@@ -3685,7 +3685,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
         */
 
        if(fsp->is_directory || fsp->fh->fd == -1) {
-               if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
+               if(vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf) != 0)
                        return map_nt_error_from_unix(errno);
        } else {
                if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
@@ -3730,7 +3730,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
                 */
 
                if(fsp->is_directory) {
-                       if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
+                       if(vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
+                                             &sbuf) != 0) {
                                return map_nt_error_from_unix(errno);
                        }
                } else {
@@ -3738,7 +3739,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
                        int sret;
 
                        if(fsp->fh->fd == -1)
-                               sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
+                               sret = vfs_stat_smb_fname(fsp->conn,
+                                                         fsp->fsp_name,
+                                                         &sbuf);
                        else
                                sret = SMB_VFS_FSTAT(fsp, &sbuf);
 
index 9544b845da5b0998a4993a2b892484dd79b1b12a..8cc865edebf6d1f1ed421f753281043fd8aadaec 100644 (file)
@@ -1007,8 +1007,9 @@ void reply_checkpath(struct smb_request *req)
        }
 
        if (!VALID_STAT(smb_fname->st) &&
-           (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
-               DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+           (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+               DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
+                       smb_fname_str_dbg(smb_fname), strerror(errno)));
                status = map_nt_error_from_unix(errno);
                goto path_err;
        }
@@ -1020,17 +1021,8 @@ void reply_checkpath(struct smb_request *req)
        }
 
        reply_outbuf(req, 0, 0);
- out:
-       TALLOC_FREE(smb_fname);
-       END_PROFILE(SMBcheckpath);
-       return;
 
  path_err:
-
-       TALLOC_FREE(smb_fname);
-
-       END_PROFILE(SMBcheckpath);
-
        /* We special case this - as when a Windows machine
                is parsing a path is steps through the components
                one at a time - if a component fails it expects
@@ -1047,10 +1039,15 @@ void reply_checkpath(struct smb_request *req)
                 */
                reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
                                ERRDOS, ERRbadpath);
-               return;
+               goto out;
        }
 
        reply_nterror(req, status);
+
+ out:
+       TALLOC_FREE(smb_fname);
+       END_PROFILE(SMBcheckpath);
+       return;
 }
 
 /****************************************************************************
@@ -1104,8 +1101,10 @@ void reply_getatr(struct smb_request *req)
                        goto out;
                }
                if (!VALID_STAT(smb_fname->st) &&
-                   (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
-                       DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+                   (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+                       DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
+                                smb_fname_str_dbg(smb_fname),
+                                strerror(errno)));
                        reply_unixerror(req, ERRDOS,ERRbadfile);
                        goto out;
                }
@@ -1133,10 +1132,12 @@ void reply_getatr(struct smb_request *req)
                      SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
        }
 
-       DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
+       DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
+                smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
 
  out:
        TALLOC_FREE(smb_fname);
+       TALLOC_FREE(fname);
        END_PROFILE(SMBgetatr);
        return;
 }
@@ -2243,8 +2244,7 @@ void reply_ctemp(struct smb_request *req)
                goto out;
        }
 
-       SET_STAT_INVALID(smb_fname->st);
-       SMB_VFS_STAT(conn, smb_fname->base_name, &smb_fname->st);
+       SMB_VFS_STAT(conn, smb_fname);
 
        /* We should fail if file does not exist. */
        status = SMB_VFS_CREATE_FILE(
@@ -2377,16 +2377,16 @@ static NTSTATUS do_unlink(connection_struct *conn,
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
        }
 
+       if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+               return map_nt_error_from_unix(errno);
+       }
+
        status = get_full_smb_filename(smb_fname, smb_fname, &fname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-
-       if (SMB_VFS_LSTAT(conn, fname, &smb_fname->st) != 0) {
-               return map_nt_error_from_unix(errno);
-       }
-
        fattr = dos_mode(conn, fname, &smb_fname->st);
+       TALLOC_FREE(fname);
 
        if (dirtype & FILE_ATTRIBUTE_NORMAL) {
                dirtype = aDIR|aARCH|aRONLY;
@@ -5259,6 +5259,8 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
 
        while((dname = ReadDirName(dir_hnd, &offset, &st))) {
                char *fullname = NULL;
+               struct smb_filename *smb_fname = NULL;
+               NTSTATUS status;
 
                if (ISDOT(dname) || ISDOTDOT(dname)) {
                        continue;
@@ -5275,29 +5277,37 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                                dname);
                if (!fullname) {
                        errno = ENOMEM;
-                       ret = False;
-                       break;
+                       goto err_break;
                }
 
-               if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
-                       ret = False;
-                       break;
+               status = create_synthetic_smb_fname(talloc_tos(), fullname,
+                                                   NULL, NULL, &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto err_break;
+               }
+
+               if(SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+                       goto err_break;
                }
 
-               if(st.st_ex_mode & S_IFDIR) {
+               if(smb_fname->st.st_ex_mode & S_IFDIR) {
                        if(!recursive_rmdir(ctx, conn, fullname)) {
-                               ret = False;
-                               break;
+                               goto err_break;
                        }
                        if(SMB_VFS_RMDIR(conn,fullname) != 0) {
-                               ret = False;
-                               break;
+                               goto err_break;
                        }
                } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
-                       ret = False;
-                       break;
+                       goto err_break;
                }
+               TALLOC_FREE(smb_fname);
+               TALLOC_FREE(fullname);
+               continue;
+        err_break:
+               TALLOC_FREE(smb_fname);
                TALLOC_FREE(fullname);
+               ret = false;
+               break;
        }
        TALLOC_FREE(dir_hnd);
        return ret;
@@ -5315,13 +5325,13 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
        SMB_STRUCT_STAT st;
 
        /* Might be a symlink. */
-       if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+       if(vfs_lstat_smb_fname(conn, directory, &st) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
        if (S_ISLNK(st.st_ex_mode)) {
                /* Is what it points to a directory ? */
-               if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+               if(vfs_stat_smb_fname(conn, directory, &st) != 0) {
                        return map_nt_error_from_unix(errno);
                }
                if (!(S_ISDIR(st.st_ex_mode))) {
@@ -5398,7 +5408,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                                break;
                        }
 
-                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
+                       if(vfs_lstat_smb_fname(conn,fullname, &st) != 0) {
                                break;
                        }
                        if(st.st_ex_mode & S_IFDIR) {
@@ -5817,10 +5827,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /*
-        * Have vfs_object_exist also fill sbuf1
-        */
-       dst_exists = vfs_object_exist(conn, newname, &sbuf1);
+       dst_exists = vfs_stat_smb_fname(conn, newname, &sbuf1) == 0;
 
        if(!replace_if_exists && dst_exists) {
                DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
@@ -5846,9 +5853,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
        } else {
                int ret = -1;
                if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+                       ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
                } else {
-                       ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+
+                       ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
                }
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
@@ -6005,7 +6013,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
        if (!src_has_wild) {
                files_struct *fsp;
-               char *fname_src = NULL;
                char *fname_dst = NULL;
 
                /*
@@ -6063,24 +6070,17 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        smb_fname_dst->base_name = fname_dst_mod;
                }
 
-               status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto out;
-               }
-
                ZERO_STRUCT(smb_fname_src->st);
                if (posix_pathnames) {
-                       SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
+                       SMB_VFS_LSTAT(conn, smb_fname_src);
                } else {
-                       SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
+                       SMB_VFS_STAT(conn, smb_fname_src);
                }
 
                if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
                        create_options |= FILE_DIRECTORY_FILE;
                }
 
-               TALLOC_FREE(fname_src);
-
                status = SMB_VFS_CREATE_FILE(
                        conn,                           /* conn */
                        req,                            /* req */
@@ -6108,7 +6108,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
                status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
                if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(fname_src);
                        goto out;
                }
 
@@ -6159,7 +6158,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 
        while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
                files_struct *fsp = NULL;
-               char *fname_src = NULL;
                char *fname_dst = NULL;
                char *destname = NULL;
                bool sysdir_entry = False;
@@ -6212,20 +6210,13 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                TALLOC_FREE(smb_fname_dst->base_name);
                smb_fname_dst->base_name = destname;
 
-               status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto out;
-               }
-
                ZERO_STRUCT(smb_fname_src->st);
                if (posix_pathnames) {
-                       SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
+                       SMB_VFS_LSTAT(conn, smb_fname_src);
                } else {
-                       SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
+                       SMB_VFS_STAT(conn, smb_fname_src);
                }
 
-               TALLOC_FREE(fname_src);
-
                create_options = 0;
 
                if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
@@ -6416,7 +6407,6 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
 {
        struct smb_filename *smb_fname_dst_tmp = NULL;
        char *fname_src = NULL;
-       char *fname_dst = NULL;
        SMB_OFF_T ret=-1;
        files_struct *fsp1,*fsp2;
        uint32 dosattrs;
@@ -6502,17 +6492,10 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
 
        TALLOC_FREE(fname_src);
 
-       status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-
-       if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
+       if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
                ZERO_STRUCTP(&smb_fname_dst_tmp->st);
        }
 
-       TALLOC_FREE(fname_dst);
-
        /* Open the dst file for writing. */
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
@@ -7509,9 +7492,9 @@ void reply_setattrE(struct smb_request *req)
                int ret = -1;
 
                if (fsp->posix_open) {
-                       ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
+                       ret = vfs_lstat_smb_fname(conn, fsp->fsp_name, &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
+                       ret = vfs_stat_smb_fname(conn, fsp->fsp_name, &sbuf);
                }
                if (ret == -1) {
                        status = map_nt_error_from_unix(errno);
index 508f71b44eed77c6bec3ab1439b900c1f6361a8d..0124b2b047cbdabf72bd816b5ad8acd5315ad1e6 100644 (file)
@@ -643,7 +643,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                                        NTSTATUS *pstatus)
 {
        connection_struct *conn;
-       SMB_STRUCT_STAT st;
+       struct smb_filename *smb_fname_cpath = NULL;
        fstring dev;
        int ret;
        char addr[INET6_ADDRSTRLEN];
@@ -651,7 +651,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        NTSTATUS status;
 
        fstrcpy(dev, pdev);
-       SET_STAT_INVALID(st);
 
        if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
                return NULL;
@@ -990,14 +989,21 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        /* Any error exit after here needs to call the disconnect hook. */
        on_err_call_dis_hook = true;
 
+       status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
+                                           NULL, NULL, &smb_fname_cpath);
+       if (!NT_STATUS_IS_OK(status)) {
+               *pstatus = status;
+               goto err_root_exit;
+       }
+
        /* win2000 does not check the permissions on the directory
           during the tree connect, instead relying on permission
           check during individual operations. To match this behaviour
           I have disabled this chdir check (tridge) */
        /* the alternative is just to check the directory exists */
-       if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
-           !S_ISDIR(st.st_ex_mode)) {
-               if (ret == 0 && !S_ISDIR(st.st_ex_mode)) {
+       if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
+           !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
+               if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
                        DEBUG(0,("'%s' is not a directory, when connecting to "
                                 "[%s]\n", conn->connectpath,
                                 lp_servicename(snum)));
@@ -1059,7 +1065,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        return(conn);
 
   err_root_exit:
-
+       TALLOC_FREE(smb_fname_cpath);
        change_to_root_user();
        if (on_err_call_dis_hook) {
                /* Call VFS disconnect hook */
index 2f7d16790d0caee200f4ebe06b7228f0d9ee8677..daed9f8225dbfeb4ed1264fd00efe76ab0344900 100644 (file)
@@ -274,7 +274,7 @@ bool stat_cache_lookup(connection_struct *conn,
                  "-> [%s]\n", chk_name, translated_path ));
        DO_PROFILE_INC(statcache_hits);
 
-       if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
+       if (vfs_stat_smb_fname(conn, translated_path, pst) != 0) {
                /* Discard this entry - it doesn't exist in the filesystem. */
                memcache_delete(smbd_memcache(), STAT_CACHE,
                                data_blob_const(chk_name, strlen(chk_name)));
index ca90c5ae699218a44c85f882a78c069444915ebd..a7d5c427d39197881f273505343ce97ea4d93d7d 100644 (file)
@@ -1395,14 +1395,17 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        }
 
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
-                               if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
+                               if (vfs_lstat_smb_fname(conn, pathreal,
+                                                       &sbuf) != 0) {
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
                                        TALLOC_FREE(pathreal);
                                        TALLOC_FREE(fname);
                                        continue;
                                }
-                       } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+                       } else if (!VALID_STAT(sbuf) &&
+                                  vfs_stat_smb_fname(conn, pathreal,
+                                                     &sbuf) != 0) {
                                /* Needed to show the msdfs symlinks as
                                 * directories */
 
@@ -2626,7 +2629,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
 
        DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
 
-       if(SMB_VFS_STAT(conn,".",&st)!=0) {
+       if(vfs_stat_smb_fname(conn,".",&st)!=0) {
                DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
                reply_doserror(req, ERRSRV, ERRinvdevice);
                return;
@@ -3871,13 +3874,13 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        char *lock_data = NULL;
        bool ms_dfs_link = false;
        TALLOC_CTX *ctx = talloc_tos();
+       NTSTATUS status = NT_STATUS_OK;
 
        if (!params) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
 
-       ZERO_STRUCT(sbuf);
        ZERO_STRUCT(write_time_ts);
 
        if (tran_call == TRANSACT2_QFILEINFO) {
@@ -3915,6 +3918,13 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        return;
                }
 
+               status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+                                                         NULL, &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+
                if(fsp->fake_file_handle) {
                        /*
                         * This is actually for the QUOTA_FAKE_FILE --metze
@@ -3931,18 +3941,25 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
-                               if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
-                                       DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+                               if (SMB_VFS_LSTAT(conn, smb_fname)) {
+                                       DEBUG(3,("call_trans2qfilepathinfo: "
+                                                "SMB_VFS_LSTAT of %s failed "
+                                                "(%s)\n",
+                                                smb_fname_str_dbg(smb_fname),
+                                                strerror(errno)));
                                        reply_unixerror(req,ERRDOS,ERRbadpath);
                                        return;
                                }
-                       } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+                       } else if (SMB_VFS_STAT(conn, smb_fname)) {
+                               DEBUG(3,("call_trans2qfilepathinfo: "
+                                        "SMB_VFS_STAT of %s failed (%s)\n",
+                                        smb_fname_str_dbg(smb_fname),
+                                        strerror(errno)));
                                reply_unixerror(req, ERRDOS, ERRbadpath);
                                return;
                        }
 
-                       fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
                        get_file_infos(fileid, &delete_pending, &write_time_ts);
                } else {
                        /*
@@ -3952,19 +3969,18 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                return;
                        }
 
-                       if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
-                               DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
+                       if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+                               DEBUG(3, ("fstat of fnum %d failed (%s)\n",
+                                         fsp->fnum, strerror(errno)));
                                reply_unixerror(req, ERRDOS, ERRbadfid);
                                return;
                        }
                        pos = fsp->fh->position_information;
-                       fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
                        get_file_infos(fileid, &delete_pending, &write_time_ts);
                }
 
        } else {
-               NTSTATUS status = NT_STATUS_OK;
-
                /* qpathinfo */
                if (total_params < 7) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -4005,41 +4021,50 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               sbuf = smb_fname->st;
-
+               /* If this is a stream, check if there is a delete_pending. */
                if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
-                   && is_ntfs_stream_name(fname)) {
-                       char *base;
-                       SMB_STRUCT_STAT bsbuf;
-
-                       status = split_ntfs_stream_name(talloc_tos(), fname,
-                                                       &base, NULL);
+                   && is_ntfs_stream_smb_fname(smb_fname)) {
+                       struct smb_filename *smb_fname_base = NULL;
+
+                       /* 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)) {
-                               DEBUG(10, ("create_file_unixpath: "
-                                       "split_ntfs_stream_name failed: %s\n",
-                                       nt_errstr(status)));
                                reply_nterror(req, status);
                                return;
                        }
 
-                       SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
-
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
-                               if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
-                                       DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
+                               if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
+                                       DEBUG(3,("call_trans2qfilepathinfo: "
+                                                "SMB_VFS_LSTAT of %s failed "
+                                                "(%s)\n",
+                                                smb_fname_str_dbg(smb_fname_base),
+                                                strerror(errno)));
+                                       TALLOC_FREE(smb_fname_base);
                                        reply_unixerror(req,ERRDOS,ERRbadpath);
                                        return;
                                }
                        } else {
-                               if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
-                                       DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
+                               if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
+                                       DEBUG(3,("call_trans2qfilepathinfo: "
+                                                "fileinfo of %s failed "
+                                                "(%s)\n",
+                                                smb_fname_str_dbg(smb_fname_base),
+                                                strerror(errno)));
+                                       TALLOC_FREE(smb_fname_base);
                                        reply_unixerror(req,ERRDOS,ERRbadpath);
                                        return;
                                }
                        }
 
-                       fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
+                       fileid = vfs_file_id_from_sbuf(conn,
+                                                      &smb_fname_base->st);
+                       TALLOC_FREE(smb_fname_base);
                        get_file_infos(fileid, &delete_pending, NULL);
                        if (delete_pending) {
                                reply_nterror(req, NT_STATUS_DELETE_PENDING);
@@ -4049,23 +4074,32 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                if (INFO_LEVEL_IS_UNIX(info_level)) {
                        /* Always do lstat for UNIX calls. */
-                       if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+                       if (SMB_VFS_LSTAT(conn, smb_fname)) {
+                               DEBUG(3,("call_trans2qfilepathinfo: "
+                                        "SMB_VFS_LSTAT of %s failed (%s)\n",
+                                        smb_fname_str_dbg(smb_fname),
+                                        strerror(errno)));
                                reply_unixerror(req, ERRDOS, ERRbadpath);
                                return;
                        }
 
-               } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
-                       ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
+               } else if (!VALID_STAT(smb_fname->st) &&
+                          SMB_VFS_STAT(conn, smb_fname) &&
+                          (info_level != SMB_INFO_IS_NAME_VALID)) {
+                       ms_dfs_link = check_msdfs_link(conn, fname,
+                                                      &smb_fname->st);
 
                        if (!ms_dfs_link) {
-                               DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+                               DEBUG(3,("call_trans2qfilepathinfo: "
+                                        "SMB_VFS_STAT of %s failed (%s)\n",
+                                        smb_fname_str_dbg(smb_fname),
+                                        strerror(errno)));
                                reply_unixerror(req, ERRDOS, ERRbadpath);
                                return;
                        }
                }
 
-               fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+               fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
                get_file_infos(fileid, &delete_pending, &write_time_ts);
                if (delete_pending) {
                        reply_nterror(req, NT_STATUS_DELETE_PENDING);
@@ -4073,6 +4107,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
        }
 
+       /* Set sbuf for use below. */
+       sbuf = smb_fname->st;
+
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                return;
@@ -4511,7 +4548,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                case SMB_FILE_STREAM_INFORMATION: {
                        unsigned int num_streams;
                        struct stream_struct *streams;
-                       NTSTATUS status;
 
                        DEBUG(10,("call_trans2qfilepathinfo: "
                                  "SMB_FILE_STREAM_INFORMATION\n"));
@@ -4738,7 +4774,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                case SMB_QUERY_POSIX_LOCK:
                {
-                       NTSTATUS status = NT_STATUS_INVALID_LEVEL;
                        uint64_t count;
                        uint64_t offset;
                        uint32 lock_pid;
@@ -6024,7 +6059,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
                TALLOC_FREE(parent);
        }
 
-       if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+       if (vfs_stat_smb_fname(conn, fname, psbuf) != 0) {
                status = map_nt_error_from_unix(errno);
                SMB_VFS_UNLINK(conn,fname);
                return status;
@@ -6742,8 +6777,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                return;
        }
 
-       ZERO_STRUCT(sbuf);
-
        if (tran_call == TRANSACT2_SETFILEINFO) {
                if (total_params < 4) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -6763,6 +6796,13 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        return;
                }
 
+               status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+                                                         NULL, &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+
                if(fsp->is_directory || fsp->fh->fd == -1) {
                        /*
                         * This is actually a SETFILEINFO on a directory
@@ -6771,14 +6811,21 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                         */
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
-                               if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
-                                       DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+                               if (SMB_VFS_LSTAT(conn, smb_fname)) {
+                                       DEBUG(3,("call_trans2setfilepathinfo: "
+                                                "SMB_VFS_LSTAT of %s failed "
+                                                "(%s)\n",
+                                                smb_fname_str_dbg(smb_fname),
+                                                strerror(errno)));
                                        reply_unixerror(req,ERRDOS,ERRbadpath);
                                        return;
                                }
                        } else {
-                               if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
-                                       DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+                               if (SMB_VFS_STAT(conn, smb_fname) != 0) {
+                                       DEBUG(3,("call_trans2setfilepathinfo: "
+                                                "fileinfo of %s failed (%s)\n",
+                                                smb_fname_str_dbg(smb_fname),
+                                                strerror(errno)));
                                        reply_unixerror(req,ERRDOS,ERRbadpath);
                                        return;
                                }
@@ -6809,8 +6856,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                return;
                        }
 
-                       if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
-                               DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+                       if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+                               DEBUG(3,("call_trans2setfilepathinfo: fstat "
+                                        "of fnum %d failed (%s)\n", fsp->fnum,
+                                        strerror(errno)));
                                reply_unixerror(req, ERRDOS, ERRbadfid);
                                return;
                        }
@@ -6847,23 +6896,28 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               sbuf = smb_fname->st;
-
                if (INFO_LEVEL_IS_UNIX(info_level)) {
                        /*
                         * For CIFS UNIX extensions the target name may not exist.
                         */
 
                        /* Always do lstat for UNIX calls. */
-                       SMB_VFS_LSTAT(conn,fname,&sbuf);
-
-               } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
-                       DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+                       SMB_VFS_LSTAT(conn, smb_fname);
+
+               } else if (!VALID_STAT(smb_fname->st) &&
+                          SMB_VFS_STAT(conn, smb_fname)) {
+                       DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
+                                "%s failed (%s)\n",
+                                smb_fname_str_dbg(smb_fname),
+                                strerror(errno)));
                        reply_unixerror(req, ERRDOS, ERRbadpath);
                        return;
                }
        }
 
+       /* Set sbuf for use below. */
+       sbuf = smb_fname->st;
+
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                return;
index 385454e587f835f564feb98a54a3e70594e792b8..2b4124bf7b6030e14f3006d0e1c8a03451825be6 100644 (file)
@@ -338,72 +338,19 @@ bool smbd_vfs_init(connection_struct *conn)
        return True;
 }
 
-/*******************************************************************
- Check if directory exists.
-********************************************************************/
-
-bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st)
-{
-       SMB_STRUCT_STAT st2;
-       bool ret;
-
-       if (!st)
-               st = &st2;
-
-       if (SMB_VFS_STAT(conn,dname,st) != 0)
-               return(False);
-
-       ret = S_ISDIR(st->st_ex_mode);
-       if(!ret)
-               errno = ENOTDIR;
-
-       return ret;
-}
-
-/*******************************************************************
- Check if an object exists in the vfs.
-********************************************************************/
-
-bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf)
-{
-       SMB_STRUCT_STAT st;
-
-       if (!sbuf)
-               sbuf = &st;
-
-       ZERO_STRUCTP(sbuf);
-
-       if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
-               return(False);
-       return True;
-}
-
 /*******************************************************************
  Check if a file exists in the vfs.
 ********************************************************************/
 
 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
 {
-       char *fname = NULL;
-       NTSTATUS status;
-
-       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-
-       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       if (SMB_VFS_STAT(conn, fname, &smb_fname->st) == -1) {
-               goto out;
-       }
-
        /* Only return OK if stat was successful and S_ISREG */
-       if (S_ISREG(smb_fname->st.st_ex_mode)) {
-               status = NT_STATUS_OK;
+       if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
+           S_ISREG(smb_fname->st.st_ex_mode)) {
+               return NT_STATUS_OK;
        }
- out:
-       TALLOC_FREE(fname);
-       return status;
+
+       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 }
 
 /****************************************************************************
@@ -791,10 +738,12 @@ int vfs_ChDir(connection_struct *conn, const char *path)
 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 {
         char s[PATH_MAX+1];
-       SMB_STRUCT_STAT st, st2;
-       char *result;
+       char *result = NULL;
        DATA_BLOB cache_value;
        struct file_id key;
+       struct smb_filename *smb_fname_dot = NULL;
+       struct smb_filename *smb_fname_full = NULL;
+       NTSTATUS status;
 
        *s = 0;
 
@@ -802,9 +751,14 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
                goto nocache;
        }
 
-       SET_STAT_INVALID(st);
+       status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
+                                           &smb_fname_dot);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
+       }
 
-       if (SMB_VFS_STAT(conn, ".",&st) == -1) {
+       if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
                /*
                 * Known to fail for root: the directory may be NFS-mounted
                 * and exported with root_squash (so has no root access).
@@ -814,7 +768,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
                goto nocache;
        }
 
-       key = vfs_file_id_from_sbuf(conn, &st);
+       key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
 
        if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
                             data_blob_const(&key, sizeof(key)),
@@ -825,17 +779,25 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        SMB_ASSERT((cache_value.length > 0)
                   && (cache_value.data[cache_value.length-1] == '\0'));
 
-       if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0)
-           && (st.st_ex_dev == st2.st_ex_dev) && (st.st_ex_ino == st2.st_ex_ino)
-           && (S_ISDIR(st.st_ex_mode))) {
+       status = create_synthetic_smb_fname(ctx, (char *)cache_value.data,
+                                           NULL, NULL, &smb_fname_full);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
+       }
+
+       if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
+           (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
+           (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
+           (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
                /*
                 * Ok, we're done
                 */
-               result = talloc_strdup(ctx, (char *)cache_value.data);
+               result = talloc_strdup(ctx, smb_fname_full->base_name);
                if (result == NULL) {
                        errno = ENOMEM;
                }
-               return result;
+               goto out;
        }
 
  nocache:
@@ -849,11 +811,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        if (!SMB_VFS_GETWD(conn,s)) {
                DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
                          strerror(errno)));
-               return NULL;
+               goto out;
        }
 
-       if (lp_getwd_cache() && VALID_STAT(st)) {
-               key = vfs_file_id_from_sbuf(conn, &st);
+       if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
+               key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
 
                memcache_add(smbd_memcache(), GETWD_CACHE,
                             data_blob_const(&key, sizeof(key)),
@@ -864,6 +826,10 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        if (result == NULL) {
                errno = ENOMEM;
        }
+
+ out:
+       TALLOC_FREE(smb_fname_dot);
+       TALLOC_FREE(smb_fname_full);
        return result;
 }
 
@@ -997,7 +963,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 #ifdef S_ISLNK
         if (!lp_symlinks(SNUM(conn))) {
                 SMB_STRUCT_STAT statbuf;
-                if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
+                if ( (vfs_lstat_smb_fname(conn,fname,&statbuf) != -1) &&
                                 (S_ISLNK(statbuf.st_ex_mode)) ) {
                        if (free_resolved_name) {
                                SAFE_FREE(resolved_name);
index f1f4aed77c1e933b6b5650000cd02bbc3ec3f427..0a682c7fd91bd13684b73bde7d83bffd8626eacd 100644 (file)
@@ -554,19 +554,30 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
        const char *group;
        struct passwd *pwd = NULL;
        struct group *grp = NULL;
+       struct smb_filename *smb_fname = NULL;
        SMB_STRUCT_STAT st;
        time_t tmp_time;
+       NTSTATUS status;
 
        if (argc != 2) {
                printf("Usage: stat <fname>\n");
                return NT_STATUS_OK;
        }
 
-       ret = SMB_VFS_STAT(vfs->conn, argv[1], &st);
+       status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       ret = SMB_VFS_STAT(vfs->conn, smb_fname);
        if (ret == -1) {
                printf("stat: error=%d (%s)\n", errno, strerror(errno));
+               TALLOC_FREE(smb_fname);
                return NT_STATUS_UNSUCCESSFUL;
        }
+       st = smb_fname->st;
+       TALLOC_FREE(smb_fname);
 
        pwd = sys_getpwuid(st.st_ex_uid);
        if (pwd != NULL) user = pwd->pw_name;
@@ -684,18 +695,29 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
        const char *group;
        struct passwd *pwd = NULL;
        struct group *grp = NULL;
+       struct smb_filename *smb_fname = NULL;
        SMB_STRUCT_STAT st;
        time_t tmp_time;
+       NTSTATUS status;
 
        if (argc != 2) {
                printf("Usage: lstat <path>\n");
                return NT_STATUS_OK;
        }
 
-       if (SMB_VFS_LSTAT(vfs->conn, argv[1], &st) == -1) {
+       status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
+                                                 &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (SMB_VFS_LSTAT(vfs->conn, smb_fname) == -1) {
                printf("lstat: error=%d (%s)\n", errno, strerror(errno));
+               TALLOC_FREE(smb_fname);
                return NT_STATUS_UNSUCCESSFUL;
        }
+       st = smb_fname->st;
+       TALLOC_FREE(smb_fname);
 
        pwd = sys_getpwuid(st.st_ex_uid);
        if (pwd != NULL) user = pwd->pw_name;