s3: VFS: Change SMB_VFS_GETWD to return struct smb_filename * instead of char *.
authorJeremy Allison <jra@samba.org>
Thu, 29 Jun 2017 21:32:47 +0000 (14:32 -0700)
committerJeremy Allison <jra@samba.org>
Sat, 1 Jul 2017 01:07:11 +0000 (03:07 +0200)
We need to migrate all pathname based VFS calls to use a struct
to finish modernising the VFS with extra timestamp and flags parameters.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
23 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
lib/util/memcache.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_acl_common.c
source3/modules/vfs_ceph.c
source3/modules/vfs_default.c
source3/modules/vfs_dirsort.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_glusterfs.c
source3/modules/vfs_netatalk.c
source3/modules/vfs_preopen.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_time_audit.c
source3/smbd/dir.c
source3/smbd/msdfs.c
source3/smbd/open.c
source3/smbd/proto.h
source3/smbd/service.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c
source3/torture/torture.c

index fd81ca0..8bfc520 100644 (file)
@@ -419,7 +419,8 @@ static int skel_chdir(vfs_handle_struct *handle,
        return -1;
 }
 
-static char *skel_getwd(vfs_handle_struct *handle)
+static struct smb_filename *skel_getwd(vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx)
 {
        errno = ENOSYS;
        return NULL;
index 4c061ca..a5ba6a9 100644 (file)
@@ -521,9 +521,10 @@ static int skel_chdir(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
 }
 
-static char *skel_getwd(vfs_handle_struct *handle)
+static struct smb_filename *skel_getwd(vfs_handle_struct *handle,
+                                       TALLOC_CTX *ctx)
 {
-       return SMB_VFS_NEXT_GETWD(handle);
+       return SMB_VFS_NEXT_GETWD(handle, ctx);
 }
 
 static int skel_ntimes(vfs_handle_struct *handle,
index 9e9a208..acd663c 100644 (file)
@@ -54,6 +54,7 @@ static bool memcache_is_talloc(enum memcache_number n)
        case PDB_GETPWSID_CACHE:
        case SINGLETON_CACHE_TALLOC:
        case SHARE_MODE_LOCK_CACHE:
+       case GETWD_CACHE:
                result = true;
                break;
        default:
index f5ac5b5..716e194 100644 (file)
                to const struct smb_filename * */
 /* Version 37 - Change chdir from const char *
                to const struct smb_filename * */
+/* Version 37 - Change getwd from char *
+               to const struct smb_filename * */
+/* Version 37 - Change conn->cwd from char *
+               to struct smb_filename * */
 
 #define SMB_VFS_INTERFACE_VERSION 37
 
@@ -419,7 +423,7 @@ typedef struct connection_struct {
        enum timestamp_set_resolution ts_res;
        char *connectpath;
        char *origpath;
-       char *cwd; /* Working directory. */
+       struct smb_filename *cwd_fname; /* Working directory. */
 
        struct vfs_handle_struct *vfs_handles;          /* for the new plugins */
 
@@ -735,7 +739,8 @@ struct vfs_fn_pointers {
                        gid_t gid);
        int (*chdir_fn)(struct vfs_handle_struct *handle,
                         const struct smb_filename *smb_fname);
-       char *(*getwd_fn)(struct vfs_handle_struct *handle);
+       struct smb_filename *(*getwd_fn)(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *mem_ctx);
        int (*ntimes_fn)(struct vfs_handle_struct *handle,
                         const struct smb_filename *smb_fname,
                         struct smb_file_time *ft);
@@ -1237,7 +1242,8 @@ int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
                        gid_t gid);
 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname);
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle);
+struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx);
 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        struct smb_file_time *ft);
index 367009b..29f0338 100644 (file)
 #define SMB_VFS_NEXT_CHDIR(handle, smb_fname) \
        smb_vfs_call_chdir((handle)->next, (smb_fname))
 
-#define SMB_VFS_GETWD(conn) \
-       smb_vfs_call_getwd((conn)->vfs_handles)
-#define SMB_VFS_NEXT_GETWD(handle) \
-       smb_vfs_call_getwd((handle)->next)
+#define SMB_VFS_GETWD(conn, ctx) \
+       smb_vfs_call_getwd((conn)->vfs_handles, (ctx))
+#define SMB_VFS_NEXT_GETWD(handle, ctx) \
+       smb_vfs_call_getwd((handle)->next, (ctx))
 
 #define SMB_VFS_NTIMES(conn, path, ts) \
        smb_vfs_call_ntimes((conn)->vfs_handles, (path), (ts))
index 3b054df..6abf1e3 100644 (file)
@@ -1300,15 +1300,13 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
        struct smb_filename local_fname = {0};
        struct smb_filename parent_dir_fname = {0};
        int saved_errno = 0;
-       char *saved_dir = NULL;
-       struct smb_filename saved_dir_fname = {0};
+       struct smb_filename *saved_dir_fname = NULL;
 
-       saved_dir = vfs_GetWd(talloc_tos(),conn);
-       if (!saved_dir) {
+       saved_dir_fname = vfs_GetWd(talloc_tos(),conn);
+       if (saved_dir_fname == NULL) {
                saved_errno = errno;
                goto out;
        }
-       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
 
        if (!parent_dirname(talloc_tos(), smb_fname->base_name,
                        &parent_dir, &final_component)) {
@@ -1374,8 +1372,9 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
 
        TALLOC_FREE(parent_dir);
 
-       if (saved_dir) {
-               vfs_ChDir(conn, &saved_dir_fname);
+       if (saved_dir_fname) {
+               vfs_ChDir(conn, saved_dir_fname);
+               TALLOC_FREE(saved_dir_fname);
        }
        if (saved_errno) {
                errno = saved_errno;
index 6b298a2..7d3f4a7 100644 (file)
@@ -949,11 +949,16 @@ static int cephwrap_chdir(struct vfs_handle_struct *handle,
        WRAP_RETURN(result);
 }
 
-static char *cephwrap_getwd(struct vfs_handle_struct *handle)
+static struct smb_filename *cephwrap_getwd(struct vfs_handle_struct *handle,
+                       TALLOC_CTX *ctx)
 {
        const char *cwd = ceph_getcwd(handle->data);
        DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle, cwd);
-       return SMB_STRDUP(cwd);
+       return synthetic_smb_fname(ctx,
+                               cwd,
+                               NULL,
+                               NULL,
+                               0);
 }
 
 static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
index 7a2fae2..b01a007 100644 (file)
@@ -2099,14 +2099,24 @@ static int vfswrap_chdir(vfs_handle_struct *handle,
        return result;
 }
 
-static char *vfswrap_getwd(vfs_handle_struct *handle)
+static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx)
 {
        char *result;
+       struct smb_filename *smb_fname = NULL;
 
        START_PROFILE(syscall_getwd);
        result = sys_getwd();
        END_PROFILE(syscall_getwd);
-       return result;
+       smb_fname = synthetic_smb_fname(ctx,
+                               result,
+                               NULL,
+                               NULL,
+                               0);
+       if (smb_fname == NULL) {
+               SAFE_FREE(result);
+       }
+       return smb_fname;
 }
 
 /*********************************************************************
index fc35186..c23f6f0 100644 (file)
@@ -154,7 +154,15 @@ static DIR *dirsort_opendir(vfs_handle_struct *handle,
        }
 
        if (ISDOT(data->smb_fname->base_name)) {
-               data->smb_fname->base_name = vfs_GetWd(data, handle->conn);
+               struct smb_filename *cwd_fname = vfs_GetWd(data, handle->conn);
+               if (cwd_fname == NULL) {
+                       TALLOC_FREE(data);
+                       return NULL;
+               }
+               TALLOC_FREE(data->smb_fname->base_name);
+               data->smb_fname->base_name = talloc_move(data->smb_fname,
+                                               &cwd_fname->base_name);
+               TALLOC_FREE(cwd_fname);
        }
 
        /* Open the underlying directory and count the number of entries */
index 5d35c34..5178324 100644 (file)
@@ -1521,14 +1521,15 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle,
        return result;
 }
 
-static char *smb_full_audit_getwd(vfs_handle_struct *handle)
+static struct smb_filename *smb_full_audit_getwd(vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx)
 {
-       char *result;
+       struct smb_filename *result;
 
-       result = SMB_VFS_NEXT_GETWD(handle);
+       result = SMB_VFS_NEXT_GETWD(handle, ctx);
        
        do_log(SMB_VFS_OP_GETWD, (result != NULL), handle, "%s",
-               result == NULL? "" : result);
+               result == NULL? "" : result->base_name);
 
        return result;
 }
index 833f093..52539b3 100644 (file)
@@ -1076,10 +1076,12 @@ static int vfs_gluster_chdir(struct vfs_handle_struct *handle,
        return glfs_chdir(handle->data, smb_fname->base_name);
 }
 
-static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
+static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx)
 {
        char *cwd;
        char *ret;
+       struct smb_filename *smb_fname = NULL;
 
        cwd = SMB_CALLOC_ARRAY(char, PATH_MAX);
        if (cwd == NULL) {
@@ -1090,7 +1092,13 @@ static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
        if (ret == 0) {
                free(cwd);
        }
-       return ret;
+       smb_fname = synthetic_smb_fname(ctx,
+                                       ret,
+                                       NULL,
+                                       NULL,
+                                       0);
+       free(cwd);
+       return smb_fname;
 }
 
 static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
index 5715c6d..16c129d 100644 (file)
@@ -234,7 +234,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle,
        const char *path = smb_fname->base_name;
        char *dpath;
 
-       if (!handle->conn->cwd || !path) goto exit_rmdir;
+       if (!handle->conn->cwd_fname->base_name || !path) goto exit_rmdir;
 
        /* due to there is no way to change bDeleteVetoFiles variable
         * from this module, gotta use talloc stuff..
@@ -246,7 +246,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle,
                goto exit_rmdir;
 
        if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", 
-         handle->conn->cwd, path, add ? "/"APPLEDOUBLE : "")))
+         handle->conn->cwd_fname->base_name, path, add ? "/"APPLEDOUBLE : "")))
                goto exit_rmdir;
 
        atalk_rrmdir(ctx, dpath);
@@ -277,7 +277,7 @@ static int atalk_rename(struct vfs_handle_struct *handle,
                return ret;
        }
 
-       if (atalk_build_paths(talloc_tos(), handle->conn->cwd, oldname,
+       if (atalk_build_paths(talloc_tos(), handle->conn->cwd_fname->base_name, oldname,
                              &adbl_path, &orig_path, &adbl_info,
                              &orig_info) != 0)
                goto exit_rename;
@@ -338,7 +338,8 @@ static int atalk_unlink(struct vfs_handle_struct *handle,
                }
        }
 
-       if (atalk_build_paths(talloc_tos(), handle->conn->cwd, path,
+       if (atalk_build_paths(talloc_tos(),
+                               handle->conn->cwd_fname->base_name, path,
                              &adbl_path, &orig_path,
                              &adbl_info, &orig_info) != 0)
                goto exit_unlink;
@@ -375,7 +376,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle,
                return ret;
 
        ret1 = atalk_build_paths(ctx,
-                       handle->conn->cwd,
+                       handle->conn->cwd_fname->base_name,
                        smb_fname->base_name,
                        &adbl_path,
                        &orig_path,
@@ -414,9 +415,10 @@ static int atalk_chown(struct vfs_handle_struct *handle,
        if (!(ctx = talloc_init("chown_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, handle->conn->cwd, smb_fname->base_name,
-                             &adbl_path, &orig_path,
-                             &adbl_info, &orig_info) != 0)
+       if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name,
+                               smb_fname->base_name,
+                               &adbl_path, &orig_path,
+                               &adbl_info, &orig_info) != 0)
                goto exit_chown;
 
        if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) {
@@ -450,9 +452,10 @@ static int atalk_lchown(struct vfs_handle_struct *handle,
        if (!(ctx = talloc_init("lchown_file")))
                return ret;
 
-       if (atalk_build_paths(ctx, handle->conn->cwd, smb_fname->base_name,
-                             &adbl_path, &orig_path,
-                             &adbl_info, &orig_info) != 0)
+       if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name,
+                               smb_fname->base_name,
+                               &adbl_path, &orig_path,
+                               &adbl_info, &orig_info) != 0)
                goto exit_lchown;
 
        if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) {
index 12ec476..18b01e6 100644 (file)
@@ -408,7 +408,8 @@ static int preopen_open(vfs_handle_struct *handle,
 
        TALLOC_FREE(state->template_fname);
        state->template_fname = talloc_asprintf(
-               state, "%s/%s", fsp->conn->cwd, smb_fname->base_name);
+               state, "%s/%s",
+               fsp->conn->cwd_fname->base_name, smb_fname->base_name);
 
        if (state->template_fname == NULL) {
                return res;
index 4b5a7bc..b20213a 100644 (file)
@@ -1523,19 +1523,19 @@ static void store_cwd_data(vfs_handle_struct *handle,
                                const char *connectpath)
 {
        struct shadow_copy2_private *priv = NULL;
-       char *cwd = NULL;
+       struct smb_filename *cwd_fname = NULL;
 
        SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
                                return);
 
        TALLOC_FREE(priv->shadow_cwd);
-       cwd = SMB_VFS_NEXT_GETWD(handle);
-       if (cwd == NULL) {
+       cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());
+       if (cwd_fname == NULL) {
                smb_panic("getwd failed\n");
        }
-       DBG_DEBUG("shadow cwd = %s\n", cwd);
-       priv->shadow_cwd = talloc_strdup(priv, cwd);
-       SAFE_FREE(cwd);
+       DBG_DEBUG("shadow cwd = %s\n", cwd_fname->base_name);
+       priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);
+       TALLOC_FREE(cwd_fname);
        if (priv->shadow_cwd == NULL) {
                smb_panic("talloc failed\n");
        }
index 820de3f..22075e7 100644 (file)
@@ -1257,14 +1257,15 @@ static int smb_time_audit_chdir(vfs_handle_struct *handle,
        return result;
 }
 
-static char *smb_time_audit_getwd(vfs_handle_struct *handle)
+static struct smb_filename *smb_time_audit_getwd(vfs_handle_struct *handle,
+                                       TALLOC_CTX *mem_ctx)
 {
-       char *result;
+       struct smb_filename *result;
        struct timespec ts1,ts2;
        double timediff;
 
        clock_gettime_mono(&ts1);
-       result = SMB_VFS_NEXT_GETWD(handle);
+       result = SMB_VFS_NEXT_GETWD(handle, mem_ctx);
        clock_gettime_mono(&ts2);
        timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
 
index 9391e3c..6b77409 100644 (file)
@@ -400,17 +400,14 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
 {
        struct smb_Dir *dir_hnd = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
-       struct smb_filename saved_dir_fname = {0};
-       char *saved_dir = vfs_GetWd(talloc_tos(), conn);
+       struct smb_filename *saved_dir_fname = vfs_GetWd(talloc_tos(), conn);
        struct privilege_paths *priv_paths = req->priv_paths;
        int ret;
 
-       if (saved_dir == NULL) {
+       if (saved_dir_fname == NULL) {
                return NULL;
        }
 
-       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
-
        if (vfs_ChDir(conn, smb_dname) == -1) {
                return NULL;
        }
@@ -441,8 +438,8 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
 
   out:
 
-       vfs_ChDir(conn, &saved_dir_fname);
-       TALLOC_FREE(saved_dir);
+       vfs_ChDir(conn, saved_dir_fname);
+       TALLOC_FREE(saved_dir_fname);
        return dir_hnd;
 }
 
@@ -1683,16 +1680,13 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
 {
        struct smb_Dir *dir_hnd = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
-       struct smb_filename saved_dir_fname = {0};
-       char *saved_dir = vfs_GetWd(ctx, conn);
+       struct smb_filename *saved_dir_fname = vfs_GetWd(ctx, conn);
        NTSTATUS status;
 
-       if (saved_dir == NULL) {
+       if (saved_dir_fname == NULL) {
                return NULL;
        }
 
-       saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
-
        if (vfs_ChDir(conn, smb_dname) == -1) {
                goto out;
        }
@@ -1738,8 +1732,8 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
 
   out:
 
-       vfs_ChDir(conn, &saved_dir_fname);
-       TALLOC_FREE(saved_dir);
+       vfs_ChDir(conn, saved_dir_fname);
+       TALLOC_FREE(saved_dir_fname);
        return dir_hnd;
 }
 
index d87b9b9..3c23d74 100644 (file)
@@ -403,8 +403,7 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                                struct smb_filename **poldcwd_fname)
 {
        connection_struct *conn;
-       char *oldcwd = NULL;
-       struct smb_filename *smb_fname_oldcwd = NULL;
+       struct smb_filename *oldcwd_fname = NULL;
        struct smb_filename smb_fname_connectpath = {0};
 
        NTSTATUS status = create_conn_struct(ctx, ev,
@@ -421,25 +420,14 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
         * user we will fail.... WTF ? JRA.
         */
 
-       oldcwd = vfs_GetWd(ctx, conn);
-       if (oldcwd == NULL) {
+       oldcwd_fname = vfs_GetWd(ctx, conn);
+       if (oldcwd_fname == NULL) {
                status = map_nt_error_from_unix(errno);
                DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno)));
                conn_free(conn);
                return status;
        }
 
-       smb_fname_oldcwd = synthetic_smb_fname(ctx,
-                               oldcwd,
-                               NULL,
-                               NULL,
-                               0);
-       if (smb_fname_oldcwd == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               conn_free(conn);
-               return status;
-       }
-
        smb_fname_connectpath = (struct smb_filename) {
                .base_name = conn->connectpath
        };
@@ -449,13 +437,13 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. "
                        "Error was %s\n",
                        conn->connectpath, strerror(errno) ));
-               TALLOC_FREE(smb_fname_oldcwd);
+               TALLOC_FREE(oldcwd_fname);
                conn_free(conn);
                return status;
        }
 
        *pconn = conn;
-       *poldcwd_fname = smb_fname_oldcwd;
+       *poldcwd_fname = oldcwd_fname;
 
        return NT_STATUS_OK;
 }
index 031ba11..ac637ba 100644 (file)
@@ -411,8 +411,7 @@ static int process_symlink_open(struct connection_struct *conn,
        int fd = -1;
        char *link_target = NULL;
        int link_len = -1;
-       char *oldwd = NULL;
-       struct smb_filename oldwd_fname = {0};
+       struct smb_filename *oldwd_fname = NULL;
        size_t rootdir_len = 0;
        char *resolved_name = NULL;
        bool matched = false;
@@ -484,13 +483,11 @@ static int process_symlink_open(struct connection_struct *conn,
                goto out;
        }
 
-       oldwd = vfs_GetWd(talloc_tos(), conn);
-       if (oldwd == NULL) {
+       oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+       if (oldwd_fname == NULL) {
                goto out;
        }
 
-       oldwd_fname = (struct smb_filename) { .base_name = oldwd };
-
        /* Ensure we operate from the root of the share. */
        if (vfs_ChDir(conn, conn_rootdir_fname) == -1) {
                goto out;
@@ -512,12 +509,12 @@ static int process_symlink_open(struct connection_struct *conn,
 
        SAFE_FREE(resolved_name);
        TALLOC_FREE(link_target);
-       if (oldwd != NULL) {
-               int ret = vfs_ChDir(conn, &oldwd_fname);
+       if (oldwd_fname != NULL) {
+               int ret = vfs_ChDir(conn, oldwd_fname);
                if (ret == -1) {
                        smb_panic("unable to get back to old directory\n");
                }
-               TALLOC_FREE(oldwd);
+               TALLOC_FREE(oldwd_fname);
        }
        if (saved_errno != 0) {
                errno = saved_errno;
@@ -541,8 +538,7 @@ static int non_widelink_open(struct connection_struct *conn,
        int fd = -1;
        struct smb_filename *smb_fname_rel = NULL;
        int saved_errno = 0;
-       char *oldwd = NULL;
-       struct smb_filename oldwd_fname = {0};
+       struct smb_filename *oldwd_fname = NULL;
        char *parent_dir = NULL;
        struct smb_filename parent_dir_fname = {0};
        const char *final_component = NULL;
@@ -556,13 +552,11 @@ static int non_widelink_open(struct connection_struct *conn,
 
        parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
 
-       oldwd = vfs_GetWd(talloc_tos(), conn);
-       if (oldwd == NULL) {
+       oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+       if (oldwd_fname == NULL) {
                goto out;
        }
 
-       oldwd_fname = (struct smb_filename) { .base_name = oldwd };
-
        /* Pin parent directory in place. */
        if (vfs_ChDir(conn, &parent_dir_fname) == -1) {
                goto out;
@@ -644,12 +638,12 @@ static int non_widelink_open(struct connection_struct *conn,
        TALLOC_FREE(parent_dir);
        TALLOC_FREE(smb_fname_rel);
 
-       if (oldwd != NULL) {
-               int ret = vfs_ChDir(conn, &oldwd_fname);
+       if (oldwd_fname != NULL) {
+               int ret = vfs_ChDir(conn, oldwd_fname);
                if (ret == -1) {
                        smb_panic("unable to get back to old directory\n");
                }
-               TALLOC_FREE(oldwd);
+               TALLOC_FREE(oldwd_fname);
        }
        if (saved_errno != 0) {
                errno = saved_errno;
@@ -837,8 +831,7 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
 {
        struct smb_filename *smb_fname_parent;
        struct smb_filename *smb_fname_cwd = NULL;
-       char *saved_dir = NULL;
-       struct smb_filename smb_fname_saved_dir = {0};
+       struct smb_filename *saved_dir_fname = NULL;
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
        int ret;
@@ -869,8 +862,8 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
           should work on any UNIX (thanks tridge :-). JRA.
        */
 
-       saved_dir = vfs_GetWd(ctx,conn);
-       if (!saved_dir) {
+       saved_dir_fname = vfs_GetWd(ctx,conn);
+       if (!saved_dir_fname) {
                status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to get "
                         "current working directory. Error was %s\n",
@@ -878,8 +871,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                goto out;
        }
 
-       smb_fname_saved_dir = (struct smb_filename) { .base_name = saved_dir };
-
        /* Chdir into the new path. */
        if (vfs_ChDir(conn, smb_dname) == -1) {
                status = map_nt_error_from_unix(errno);
@@ -949,9 +940,9 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
        }
 
  chdir:
-       vfs_ChDir(conn, &smb_fname_saved_dir);
+       vfs_ChDir(conn, saved_dir_fname);
  out:
-       TALLOC_FREE(saved_dir);
+       TALLOC_FREE(saved_dir_fname);
        TALLOC_FREE(smb_fname_parent);
        TALLOC_FREE(smb_fname_cwd);
        return status;
index 4823e11..7d641bd 100644 (file)
@@ -1232,7 +1232,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
                            SMB_STRUCT_STAT *sbuf, char **talloced);
 int vfs_ChDir(connection_struct *conn,
                        const struct smb_filename *smb_fname);
-char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
+struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
 NTSTATUS check_reduced_name(connection_struct *conn,
                        const char *cwd_name,
                        const char *fname);
index 47cd0fa..ed739c9 100644 (file)
@@ -68,10 +68,17 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
 
        talloc_free(conn->connectpath);
        conn->connectpath = destname;
-       /* Ensure conn->cwd is initialized - start as conn->connectpath. */
-       TALLOC_FREE(conn->cwd);
-       conn->cwd = talloc_strdup(conn, conn->connectpath);
-       if (!conn->cwd) {
+       /*
+        * Ensure conn->cwd_fname is initialized.
+        * start as conn->connectpath.
+        */
+       TALLOC_FREE(conn->cwd_fname);
+       conn->cwd_fname = synthetic_smb_fname(conn,
+                               conn->connectpath,
+                               NULL,
+                               NULL,
+                               0);
+       if (conn->cwd_fname == NULL) {
                return false;
        }
        return true;
index 40c41ed..5c4e9c3 100644 (file)
@@ -881,9 +881,14 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
                LastDir = SMB_STRDUP(smb_fname->base_name);
 
                /* conn cache. */
-               TALLOC_FREE(conn->cwd);
-               conn->cwd = vfs_GetWd(conn, conn);
-               DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
+               TALLOC_FREE(conn->cwd_fname);
+               conn->cwd_fname = vfs_GetWd(conn, conn);
+               if (conn->cwd_fname == NULL) {
+                       smb_panic("con->cwd getwd failed\n");
+                       /* NOTREACHED */
+                       return -1;
+               }
+               DEBUG(4,("vfs_ChDir got %s\n",conn->cwd_fname->base_name));
        }
        return ret;
 }
@@ -894,14 +899,13 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
  format. Note this can be called with conn == NULL.
 ********************************************************************/
 
-char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
+struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 {
-        char *current_dir = NULL;
-       char *result = NULL;
-       DATA_BLOB cache_value;
+        struct smb_filename *current_dir_fname = NULL;
        struct file_id key;
        struct smb_filename *smb_fname_dot = NULL;
        struct smb_filename *smb_fname_full = NULL;
+       struct smb_filename *result = NULL;
 
        if (!lp_getwd_cache()) {
                goto nocache;
@@ -925,20 +929,13 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 
        key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
 
-       if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
-                            data_blob_const(&key, sizeof(key)),
-                            &cache_value)) {
-               goto nocache;
-       }
-
-       SMB_ASSERT((cache_value.length > 0)
-                  && (cache_value.data[cache_value.length-1] == '\0'));
+       smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
+                                       smbd_memcache(),
+                                       GETWD_CACHE,
+                                       data_blob_const(&key, sizeof(key)));
 
-       smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
-                                            NULL, NULL, 0);
        if (smb_fname_full == NULL) {
-               errno = ENOMEM;
-               goto out;
+               goto nocache;
        }
 
        if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
@@ -947,8 +944,10 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
            (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
                /*
                 * Ok, we're done
+                * Note: smb_fname_full is owned by smbd_memcache()
+                * so we must make a copy to return.
                 */
-               result = talloc_strdup(ctx, smb_fname_full->base_name);
+               result = cp_smb_filename(ctx, smb_fname_full);
                if (result == NULL) {
                        errno = ENOMEM;
                }
@@ -963,8 +962,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
         * systems, or the not quite so bad getwd.
         */
 
-       current_dir = SMB_VFS_GETWD(conn);
-       if (current_dir == NULL) {
+       current_dir_fname = SMB_VFS_GETWD(conn, ctx);
+       if (current_dir_fname == NULL) {
                DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
                          strerror(errno)));
                goto out;
@@ -973,21 +972,39 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        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)),
-                            data_blob_const(current_dir,
-                                               strlen(current_dir)+1));
-       }
+               /*
+                * smbd_memcache() will own current_dir_fname after the
+                * memcache_add_talloc call, so we must make
+                * a copy on ctx to return.
+                */
+               result = cp_smb_filename(ctx, current_dir_fname);
+               if (result == NULL) {
+                       errno = ENOMEM;
+               }
 
-       result = talloc_strdup(ctx, current_dir);
-       if (result == NULL) {
-               errno = ENOMEM;
+               /*
+                * Ensure the memory going into the cache
+                * doesn't have a destructor so it can be
+                * cleanly freed.
+                */
+               talloc_set_destructor(current_dir_fname, NULL);
+
+               memcache_add_talloc(smbd_memcache(),
+                               GETWD_CACHE,
+                               data_blob_const(&key, sizeof(key)),
+                               &current_dir_fname);
+               /* current_dir_fname is now == NULL here. */
+       } else {
+               /* current_dir_fname is already allocated on ctx. */
+               result = current_dir_fname;
        }
 
  out:
        TALLOC_FREE(smb_fname_dot);
-       TALLOC_FREE(smb_fname_full);
-       SAFE_FREE(current_dir);
+       /*
+        * Don't free current_dir_fname here. It's either been moved
+        * to the memcache or is being returned in result.
+        */
        return result;
 }
 
@@ -1009,7 +1026,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        char *dir_name = NULL;
        const char *last_component = NULL;
        char *resolved_name = NULL;
-       char *saved_dir = NULL;
        struct smb_filename *saved_dir_fname = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
        struct privilege_paths *priv_paths = NULL;
@@ -1045,23 +1061,12 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
                goto err;
        }
        /* Remember where we were. */
-       saved_dir = vfs_GetWd(ctx, conn);
-       if (!saved_dir) {
+       saved_dir_fname = vfs_GetWd(ctx, conn);
+       if (!saved_dir_fname) {
                status = map_nt_error_from_unix(errno);
                goto err;
        }
 
-       saved_dir_fname = synthetic_smb_fname(ctx,
-                                       saved_dir,
-                                       NULL,
-                                       NULL,
-                                       0);
-       if (saved_dir_fname == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto err;
-       }
-
-       /* Go to the parent directory to lock in memory. */
        if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
                status = map_nt_error_from_unix(errno);
                goto err;
@@ -1177,9 +1182,8 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
 
   err:
 
-       if (saved_dir_fname) {
+       if (saved_dir_fname != NULL) {
                vfs_ChDir(conn, saved_dir_fname);
-               TALLOC_FREE(saved_dir);
                TALLOC_FREE(saved_dir_fname);
        }
        SAFE_FREE(resolved_name);
@@ -2024,15 +2028,14 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                 * and always act using lchown to ensure we
                 * don't deref any symbolic links.
                 */
-               char *saved_dir = NULL;
                char *parent_dir = NULL;
                const char *final_component = NULL;
                struct smb_filename *local_smb_fname = NULL;
                struct smb_filename parent_dir_fname = {0};
-               struct smb_filename saved_dir_fname = {0};
+               struct smb_filename *saved_dir_fname = NULL;
 
-               saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
-               if (!saved_dir) {
+               saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
+               if (!saved_dir_fname) {
                        status = map_nt_error_from_unix(errno);
                        DEBUG(0,("vfs_chown_fsp: failed to get "
                                "current working directory. Error was %s\n",
@@ -2040,10 +2043,6 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                        return status;
                }
 
-               saved_dir_fname = (struct smb_filename) {
-                       .base_name = saved_dir
-               };
-
                if (!parent_dirname(talloc_tos(),
                                fsp->fsp_name->base_name,
                                &parent_dir,
@@ -2098,9 +2097,9 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
 
   out:
 
-               vfs_ChDir(fsp->conn, &saved_dir_fname);
+               vfs_ChDir(fsp->conn, saved_dir_fname);
                TALLOC_FREE(local_smb_fname);
-               TALLOC_FREE(saved_dir);
+               TALLOC_FREE(saved_dir_fname);
                TALLOC_FREE(parent_dir);
 
                return status;
@@ -2131,10 +2130,11 @@ int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
        return handle->fns->chdir_fn(handle, smb_fname);
 }
 
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
+struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
+                               TALLOC_CTX *ctx)
 {
        VFS_FIND(getwd);
-       return handle->fns->getwd_fn(handle);
+       return handle->fns->getwd_fn(handle, ctx);
 }
 
 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
index f6d9d5b..fd09df9 100644 (file)
@@ -1057,14 +1057,14 @@ static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
 
 static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
-       char *buf = SMB_VFS_GETWD(vfs->conn);
-       if (buf == NULL) {
+       struct smb_filename *smb_fname = SMB_VFS_GETWD(vfs->conn, talloc_tos());
+       if (smb_fname == NULL) {
                printf("getwd: error=%d (%s)\n", errno, strerror(errno));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       printf("getwd: %s\n", buf);
-       SAFE_FREE(buf);
+       printf("getwd: %s\n", smb_fname->base_name);
+       TALLOC_FREE(smb_fname);
        return NT_STATUS_OK;
 }
 
index 10e450e..6959b71 100644 (file)
@@ -10580,15 +10580,25 @@ static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
 static bool run_local_memcache(int dummy)
 {
        struct memcache *cache;
-       DATA_BLOB k1, k2;
-       DATA_BLOB d1, d2, d3;
-       DATA_BLOB v1, v2, v3;
+       DATA_BLOB k1, k2, k3;
+       DATA_BLOB d1, d3;
+       DATA_BLOB v1, v3;
 
        TALLOC_CTX *mem_ctx;
+       char *ptr1 = NULL;
+       char *ptr2 = NULL;
+
        char *str1, *str2;
        size_t size1, size2;
        bool ret = false;
 
+       mem_ctx = talloc_init("foo");
+       if (mem_ctx == NULL) {
+               return false;
+       }
+
+       /* STAT_CACHE TESTS */
+
        cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
 
        if (cache == NULL) {
@@ -10597,14 +10607,13 @@ static bool run_local_memcache(int dummy)
        }
 
        d1 = data_blob_const("d1", 2);
-       d2 = data_blob_const("d2", 2);
        d3 = data_blob_const("d3", 2);
 
        k1 = data_blob_const("d1", 2);
        k2 = data_blob_const("d2", 2);
+       k3 = data_blob_const("d3", 2);
 
        memcache_add(cache, STAT_CACHE, k1, d1);
-       memcache_add(cache, GETWD_CACHE, k2, d2);
 
        if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
                printf("could not find k1\n");
@@ -10614,40 +10623,79 @@ static bool run_local_memcache(int dummy)
                return false;
        }
 
-       if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
-               printf("could not find k2\n");
+       memcache_add(cache, STAT_CACHE, k1, d3);
+
+       if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
+               printf("could not find replaced k1\n");
                return false;
        }
-       if (!data_blob_equal(d2, v2)) {
+       if (!data_blob_equal(d3, v3)) {
                return false;
        }
 
-       memcache_add(cache, STAT_CACHE, k1, d3);
+       TALLOC_FREE(cache);
 
-       if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
-               printf("could not find replaced k1\n");
+       /* GETWD_CACHE TESTS */
+       str1 = talloc_strdup(mem_ctx, "string1");
+       if (str1 == NULL) {
                return false;
        }
-       if (!data_blob_equal(d3, v3)) {
+       ptr2 = str1; /* Keep an alias for comparison. */
+
+       str2 = talloc_strdup(mem_ctx, "string2");
+       if (str2 == NULL) {
+               return false;
+       }
+
+       cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
+       if (cache == NULL) {
+               printf("memcache_init failed\n");
+               return false;
+       }
+
+       memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
+       /* str1 == NULL now. */
+       ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
+       if (ptr1 == NULL) {
+               printf("could not find k2\n");
+               return false;
+       }
+       if (ptr1 != ptr2) {
+               printf("fetch of k2 got wrong string\n");
                return false;
        }
 
-       memcache_add(cache, GETWD_CACHE, k1, d1);
+       /* Add a blob to ensure k2 gets purged. */
+       d3 = data_blob_talloc_zero(mem_ctx, 180);
+       memcache_add(cache, STAT_CACHE, k3, d3);
 
-       if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
+       ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
+       if (ptr2 != NULL) {
                printf("Did find k2, should have been purged\n");
                return false;
        }
 
        TALLOC_FREE(cache);
-
-       cache = memcache_init(NULL, 0);
+       TALLOC_FREE(mem_ctx);
 
        mem_ctx = talloc_init("foo");
+       if (mem_ctx == NULL) {
+               return false;
+       }
+
+       cache = memcache_init(NULL, 0);
+       if (cache == NULL) {
+               return false;
+       }
 
        str1 = talloc_strdup(mem_ctx, "string1");
+       if (str1 == NULL) {
+               return false;
+       }
        str2 = talloc_strdup(mem_ctx, "string2");
-
+       if (str2 == NULL) {
+               return false;
+       }
        memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
                            data_blob_string_const("torture"), &str1);
        size1 = talloc_total_size(cache);