From 258952aa85f2a68e2d2362522f6114c6a439f1e3 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 2 Jul 2009 09:27:44 -0700 Subject: [PATCH] s3: Plumb smb_filename through SMB_VFS_UNLINK --- examples/VFS/skel_opaque.c | 5 +- examples/VFS/skel_transparent.c | 5 +- source3/include/proto.h | 2 +- source3/include/vfs.h | 5 +- source3/modules/onefs_streams.c | 35 +++-- source3/modules/vfs_acl_tdb.c | 27 ++-- source3/modules/vfs_audit.c | 7 +- source3/modules/vfs_cap.c | 25 ++- source3/modules/vfs_catia.c | 25 ++- source3/modules/vfs_default.c | 17 +- source3/modules/vfs_extd_audit.c | 9 +- source3/modules/vfs_full_audit.c | 7 +- source3/modules/vfs_netatalk.c | 33 ++-- source3/modules/vfs_onefs_shadow_copy.c | 41 ++++- source3/modules/vfs_recycle.c | 197 ++++++++++++++++-------- source3/modules/vfs_shadow_copy2.c | 14 +- source3/modules/vfs_streams_depot.c | 70 +++------ source3/modules/vfs_streams_xattr.c | 43 +++--- source3/modules/vfs_syncops.c | 7 +- source3/modules/vfs_xattr_tdb.c | 26 +++- source3/smbd/close.c | 102 +++++++----- source3/smbd/msdfs.c | 28 +++- source3/smbd/reply.c | 127 +++++++++------ source3/smbd/trans2.c | 183 ++++++++++++---------- source3/torture/cmd_vfs.c | 12 +- 25 files changed, 671 insertions(+), 381 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 5d05be9aabb..54f7ce8cf2a 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -196,9 +196,10 @@ static int skel_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) return vfswrap_lstat(NULL, smb_fname); } -static int skel_unlink(vfs_handle_struct *handle, const char *path) +static int skel_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - return vfswrap_unlink(NULL, path); + return vfswrap_unlink(NULL, smb_fname); } static int skel_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 646c6222ae7..09a926ad43a 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -189,9 +189,10 @@ static int skel_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) return SMB_VFS_NEXT_LSTAT(handle, smb_fname); } -static int skel_unlink(vfs_handle_struct *handle, const char *path) +static int skel_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - return SMB_VFS_NEXT_UNLINK(handle, path); + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); } static int skel_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) diff --git a/source3/include/proto.h b/source3/include/proto.h index a2fcd95e7d7..17c3a5135a7 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6872,7 +6872,7 @@ void reply_printwrite(struct smb_request *req); void reply_mkdir(struct smb_request *req); NTSTATUS rmdir_internals(TALLOC_CTX *ctx, connection_struct *conn, - const char *directory); + struct smb_filename *smb_dname); void reply_rmdir(struct smb_request *req); NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, diff --git a/source3/include/vfs.h b/source3/include/vfs.h index c3580da5d0f..cfa3403e82c 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -119,7 +119,7 @@ /* 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_STAT, SMB_VFS_LSTAT, - SMB_VFS_RENAME. */ + SMB_VFS_RENAME, SMB_VFS_UNLINK. */ #define SMB_VFS_INTERFACE_VERSION 26 @@ -366,7 +366,8 @@ struct vfs_ops { int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, 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 (*unlink)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname); int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode); int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, mode_t mode); int (*chown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid); diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index 8963037c224..c22fc711a0e 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -462,38 +462,49 @@ int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) return ret; } -int onefs_unlink(vfs_handle_struct *handle, const char *path) +int onefs_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { + struct smb_filename *smb_fname_onefs = NULL; int ret; bool is_stream; char *base = NULL; char *stream = NULL; int dir_fd, saved_errno; - ret = onefs_is_stream(path, &base, &stream, &is_stream); - if (ret) { - return ret; + /* Not a stream. */ + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); } - if (!is_stream) { - return SMB_VFS_NEXT_UNLINK(handle, path); + status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname, + &smb_fname_onefs); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; } - /* If it's the ::$DATA stream just unlink the base file name. */ - if (!stream) { - return SMB_VFS_NEXT_UNLINK(handle, base); + /* Default stream (the ::$DATA was just stripped off). */ + if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) { + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_onefs); + goto out; } - dir_fd = get_stream_dir_fd(handle->conn, base, NULL); + dir_fd = get_stream_dir_fd(handle->conn, smb_fname_onefs->base_name, + NULL); if (dir_fd < 0) { - return -1; + ret = -1; + goto out; } - ret = enc_unlinkat(dir_fd, stream, ENC_DEFAULT, 0); + ret = enc_unlinkat(dir_fd, smb_fname_onefs->stream_name, ENC_DEFAULT, + 0); saved_errno = errno; close(dir_fd); errno = saved_errno; + out: + TALLOC_FREE(smb_fname_onefs); return ret; } diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 9f0b0b317a5..64ad3e1a788 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -616,32 +616,41 @@ static int open_acl_tdb(vfs_handle_struct *handle, On unlink we need to delete the tdb record (if using tdb). *********************************************************************/ -static int unlink_acl_tdb(vfs_handle_struct *handle, const char *path) +static int unlink_acl_tdb(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname_tmp = NULL; struct db_context *db; + NTSTATUS status; int ret = -1; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto out; + } + if (lp_posix_pathnames()) { - ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf); + ret = SMB_VFS_LSTAT(handle->conn, smb_fname_tmp); } else { - ret = vfs_stat_smb_fname(handle->conn, path, &sbuf); + ret = SMB_VFS_STAT(handle->conn, smb_fname_tmp); } if (ret == -1) { - return -1; + goto out; } - ret = SMB_VFS_NEXT_UNLINK(handle, path); + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); if (ret == -1) { - return -1; + goto out; } - acl_tdb_delete(handle, db, &sbuf); - return 0; + acl_tdb_delete(handle, db, &smb_fname_tmp->st); + out: + return ret; } /********************************************************************* diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 809ecc9e44b..8c0141906b1 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -187,14 +187,15 @@ static int audit_rename(vfs_handle_struct *handle, return result; } -static int audit_unlink(vfs_handle_struct *handle, const char *path) +static int audit_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, path); + result = SMB_VFS_NEXT_UNLINK(handle, smb_fname); syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", - path, + smb_fname_str_dbg(smb_fname), (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 4d16aa44ae6..9348ab9554c 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -226,15 +226,34 @@ static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) return ret; } -static int cap_unlink(vfs_handle_struct *handle, const char *path) +static int cap_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - char *cappath = capencode(talloc_tos(), path); + struct smb_filename *smb_fname_tmp = NULL; + char *cappath = NULL; + NTSTATUS status; + int ret; + cappath = capencode(talloc_tos(), smb_fname->base_name); if (!cappath) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_UNLINK(handle, cappath); + + /* Setup temporary smb_filename structs. */ + status = copy_smb_filename(talloc_tos(), smb_fname, + &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + smb_fname_tmp->base_name = cappath; + + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); + + TALLOC_FREE(smb_fname_tmp); + return ret; } static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index b5283d25c2a..18db92dbb75 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -258,15 +258,34 @@ static int catia_lstat(vfs_handle_struct *handle, return ret; } -static int catia_unlink(vfs_handle_struct *handle, const char *path) +static int catia_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - char *name = to_unix(talloc_tos(), path); + struct smb_filename *smb_fname_tmp = NULL; + char *name = NULL; + NTSTATUS status; + int ret; + name = to_unix(talloc_tos(), smb_fname->base_name); if (!name) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_UNLINK(handle, name); + + /* Setup temporary smb_filename structs. */ + status = copy_smb_filename(talloc_tos(), smb_fname, + &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + smb_fname_tmp->base_name = name; + + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); + + TALLOC_FREE(smb_fname_tmp); + return ret; } static int catia_chmod(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 9a55456b0c8..c95c68fe0f1 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -524,13 +524,12 @@ static int vfswrap_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { - int result; + int result = -1; START_PROFILE(syscall_rename); if (smb_fname_src->stream_name || smb_fname_dst->stream_name) { errno = ENOENT; - result = -1; goto out; } @@ -651,12 +650,20 @@ static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle, return result; } -static int vfswrap_unlink(vfs_handle_struct *handle, const char *path) +static int vfswrap_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - int result; + int result = -1; START_PROFILE(syscall_unlink); - result = unlink(path); + + if (smb_fname->stream_name) { + errno = ENOENT; + goto out; + } + result = unlink(smb_fname->base_name); + + out: END_PROFILE(syscall_unlink); return result; } diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index f442c05c29f..68b85516ea6 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -235,20 +235,21 @@ static int audit_rename(vfs_handle_struct *handle, return result; } -static int audit_unlink(vfs_handle_struct *handle, const char *path) +static int audit_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, path); + result = SMB_VFS_NEXT_UNLINK(handle, smb_fname); if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", - path, + smb_fname->base_name, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); } DEBUG(0, ("vfs_extd_audit: unlink %s %s %s\n", - path, + smb_fname_str_dbg(smb_fname), (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : "")); diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index e20a65092d8..1f5e8333b90 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -910,13 +910,14 @@ static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle, } static int smb_full_audit_unlink(vfs_handle_struct *handle, - const char *path) + const struct smb_filename *smb_fname) { int result; - result = SMB_VFS_NEXT_UNLINK(handle, path); + result = SMB_VFS_NEXT_UNLINK(handle, smb_fname); - do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", path); + do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", + smb_fname_str_do_log(smb_fname)); return result; } diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index 0e20beca410..77107721743 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/modules/vfs_netatalk.c @@ -254,24 +254,29 @@ static int atalk_rename(struct vfs_handle_struct *handle, atalk_unlink_file(adbl_path); exit_rename: + TALLOC_FREE(oldname); TALLOC_FREE(adbl_path); TALLOC_FREE(orig_path); - TALLOC_FREE(orig_path); return ret; } -static int atalk_unlink(struct vfs_handle_struct *handle, const char *path) +static int atalk_unlink(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { int ret = 0, i; - char *adbl_path = 0; - char *orig_path = 0; + char *path = NULL; + char *adbl_path = NULL; + char *orig_path = NULL; SMB_STRUCT_STAT adbl_info; SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; + NTSTATUS status; - ret = SMB_VFS_NEXT_UNLINK(handle, path); + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); - if (!path) return ret; + status = get_full_smb_filename(talloc_tos(), smb_fname, &path); + if (!NT_STATUS_IS_OK(status)) { + return ret; + } /* no .AppleDouble sync if veto or hide list is empty, * otherwise "Cannot find the specified file" error will be caused @@ -292,15 +297,13 @@ static int atalk_unlink(struct vfs_handle_struct *handle, const char *path) else { DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", APPLEDOUBLE)); - return ret; + goto exit_unlink; } } } - if (!(ctx = talloc_init("unlink_file"))) - return ret; - - if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path, + if (atalk_build_paths(talloc_tos(), handle->conn->origpath, path, + &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) goto exit_unlink; @@ -311,8 +314,10 @@ static int atalk_unlink(struct vfs_handle_struct *handle, const char *path) atalk_unlink_file(adbl_path); -exit_unlink: - talloc_destroy(ctx); +exit_unlink: + TALLOC_FREE(path); + TALLOC_FREE(adbl_path); + TALLOC_FREE(orig_path); return ret; } diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c index 04460d6056c..1a43e0671a9 100644 --- a/source3/modules/vfs_onefs_shadow_copy.c +++ b/source3/modules/vfs_onefs_shadow_copy.c @@ -143,9 +143,6 @@ onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, return ret; \ } while (0) \ -/* - * XXX: Convert osc_canonicalize_path to use talloc instead of malloc. - */ #define SHADOW_NEXT_SMB_FNAME(op, args, rtype) do { \ char *smb_base_name_tmp = NULL; \ char *cpath = NULL; \ @@ -165,6 +162,35 @@ onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, } while (0) \ +/* + * XXX: Convert osc_canonicalize_path to use talloc instead of malloc. + */ +#define SHADOW_NEXT_SMB_FNAME_CONST(op, args, rtype) do { \ + struct smb_filename *smb_fname_tmp = NULL; \ + char *cpath = NULL; \ + char *snap_component = NULL; \ + rtype ret; \ + if (shadow_copy_match_name(smb_fname->base_name, \ + &snap_component)) { \ + cpath = osc_canonicalize_path(smb_fname->base_name, \ + snap_component); \ + smb_fname->base_name = cpath; \ + } \ + status = create_synthetic_smb_fname(talloc_tos(), \ + cpath ?: smb_fname->base_name, \ + smb_fname->stream_name, &smb_fname->st, \ + &smb_fname_tmp); \ + if (!NT_STATUS_IS_OK(status)) { \ + errno = map_errno_from_nt_status(status); \ + return ret; \ + } \ + ret = SMB_VFS_NEXT_ ## op args; \ + TALLOC_FREE(smb_fname_tmp) \ + SAFE_FREE(cpath); \ + return ret; \ + } while (0) \ + + static uint64_t onefs_shadow_copy_disk_free(vfs_handle_struct *handle, const char *path, @@ -324,11 +350,12 @@ onefs_shadow_copy_lstat(vfs_handle_struct *handle, } static int -onefs_shadow_copy_unlink(vfs_handle_struct *handle, const char *path) +onefs_shadow_copy_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SHADOW_NEXT(UNLINK, - (handle, cpath ?: path), - int); + SHADOW_NEXT_SMB_FNAME_CONST(UNLINK, + (handle, smb_fname_tmp), + int); } static int diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 3fbe8d7e55e..24166d12668 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -33,7 +33,8 @@ static int vfs_recycle_debug_level = DBGC_VFS; static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user); static void recycle_disconnect(vfs_handle_struct *handle); -static int recycle_unlink(vfs_handle_struct *handle, const char *name); +static int recycle_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname); static vfs_op_tuple recycle_ops[] = { @@ -223,17 +224,26 @@ static bool recycle_directory_exist(vfs_handle_struct *handle, const char *dname return False; } -static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname) +static bool recycle_file_exist(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT st; + struct smb_filename *smb_fname_tmp = NULL; + NTSTATUS status; + bool ret = false; - if (vfs_stat_smb_fname(handle->conn, fname, &st) == 0) { - if (S_ISREG(st.st_ex_mode)) { - return True; + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + if (SMB_VFS_STAT(handle->conn, smb_fname_tmp) == 0) { + if (S_ISREG(smb_fname_tmp->st.st_ex_mode)) { + ret = true; } } - return False; + TALLOC_FREE(smb_fname_tmp); + return ret; } /** @@ -242,16 +252,30 @@ static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname) * @param fname file name * @return size in bytes **/ -static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fname) +static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT st; + struct smb_filename *smb_fname_tmp = NULL; + NTSTATUS status; + SMB_OFF_T size; + + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + size = (SMB_OFF_T)0; + goto out; + } - 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; + if (SMB_VFS_STAT(handle->conn, smb_fname_tmp) != 0) { + DEBUG(0,("recycle: stat for %s returned %s\n", + smb_fname_str_dbg(smb_fname_tmp), strerror(errno))); + size = (SMB_OFF_T)0; + goto out; } - return(st.st_ex_size); + size = smb_fname_tmp->st.st_ex_size; + out: + TALLOC_FREE(smb_fname_tmp); + return size; } /** @@ -387,22 +411,37 @@ static bool matchparam(const char **haystack_list, const char *needle) /** * Touch access or modify date **/ -static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, +static void recycle_do_touch(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, bool touch_mtime) { - SMB_STRUCT_STAT st; + struct smb_filename *smb_fname_tmp = NULL; struct smb_file_time ft; + char *fname = NULL; + NTSTATUS status; int ret, err; ZERO_STRUCT(ft); - if (vfs_stat_smb_fname(handle->conn, fname, &st) != 0) { - DEBUG(0,("recycle: stat for %s returned %s\n", - fname, strerror(errno))); + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { return; } - ft.atime = timespec_current(); /* atime */ - ft.mtime = touch_mtime ? ft.atime : st.st_ex_mtime; /* mtime */ + + if (SMB_VFS_STAT(handle->conn, smb_fname_tmp) != 0) { + DEBUG(0,("recycle: stat for %s returned %s\n", + smb_fname_str_dbg(smb_fname_tmp), strerror(errno))); + goto out; + } + /* atime */ + ft.atime = timespec_current(); + /* mtime */ + ft.mtime = touch_mtime ? ft.atime : smb_fname_tmp->st.st_ex_mtime; + + status = get_full_smb_filename(talloc_tos(), smb_fname_tmp, &fname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } become_root(); ret = SMB_VFS_NEXT_NTIMES(handle, fname, &ft); @@ -410,20 +449,23 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, unbecome_root(); if (ret == -1 ) { DEBUG(0, ("recycle: touching %s failed, reason = %s\n", - fname, strerror(err))); + smb_fname_str_dbg(smb_fname_tmp), strerror(err))); } + + out: + TALLOC_FREE(fname); } /** * Check if file should be recycled **/ -static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) +static int recycle_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { connection_struct *conn = handle->conn; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; - struct smb_filename *smb_fname_file = NULL; struct smb_filename *smb_fname_final = NULL; const char *base; char *repository = NULL; @@ -447,19 +489,21 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) trim_char(repository, '\0', '/'); if(!repository || *(repository) == '\0') { - DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + DEBUG(3, ("recycle: repository path not set, purging %s...\n", + smb_fname_str_dbg(smb_fname))); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* we don't recycle the recycle bin... */ - if (strncmp(file_name, repository, strlen(repository)) == 0) { + if (strncmp(smb_fname->base_name, repository, + strlen(repository)) == 0) { DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n")); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } - file_size = recycle_get_file_size(handle, file_name); + file_size = recycle_get_file_size(handle, smb_fname); /* it is wrong to purge filenames only because they are empty imho * --- simo * @@ -476,14 +520,16 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) */ maxsize = recycle_maxsize(handle); if(maxsize > 0 && file_size > maxsize) { - DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + DEBUG(3, ("recycle: File %s exceeds maximum recycle size, " + "purging... \n", smb_fname_str_dbg(smb_fname))); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } minsize = recycle_minsize(handle); if(minsize > 0 && file_size < minsize) { - DEBUG(3, ("recycle: File %s lowers minimum recycle size, purging... \n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + DEBUG(3, ("recycle: File %s lowers minimum recycle size, " + "purging... \n", smb_fname_str_dbg(smb_fname))); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } @@ -500,32 +546,35 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) */ /* extract filename and path */ - base = strrchr(file_name, '/'); + base = strrchr(smb_fname->base_name, '/'); if (base == NULL) { - base = file_name; + base = smb_fname->base_name; path_name = SMB_STRDUP("/"); ALLOC_CHECK(path_name, done); } else { - path_name = SMB_STRDUP(file_name); + path_name = SMB_STRDUP(smb_fname->base_name); ALLOC_CHECK(path_name, done); - path_name[base - file_name] = '\0'; + path_name[base - smb_fname->base_name] = '\0'; base++; } - DEBUG(10, ("recycle: fname = %s\n", file_name)); /* original filename with path */ - DEBUG(10, ("recycle: fpath = %s\n", path_name)); /* original path */ - DEBUG(10, ("recycle: base = %s\n", base)); /* filename without path */ + /* original filename with path */ + DEBUG(10, ("recycle: fname = %s\n", smb_fname_str_dbg(smb_fname))); + /* original path */ + DEBUG(10, ("recycle: fpath = %s\n", path_name)); + /* filename without path */ + DEBUG(10, ("recycle: base = %s\n", base)); if (matchparam(recycle_exclude(handle), base)) { DEBUG(3, ("recycle: file %s is excluded \n", base)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } if (matchdirparam(recycle_exclude_dir(handle), path_name)) { DEBUG(3, ("recycle: directory %s is excluded \n", path_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } @@ -544,8 +593,10 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) } else { DEBUG(10, ("recycle: Creating directory %s\n", temp_name)); if (recycle_create_dir(handle, temp_name) == False) { - DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + DEBUG(3, ("recycle: Could not create directory, " + "purging %s...\n", + smb_fname_str_dbg(smb_fname))); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } } @@ -553,13 +604,27 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) { ALLOC_CHECK(final_name, done); } - DEBUG(10, ("recycle: recycled file name: %s\n", final_name)); /* new filename with path */ + + /* Create smb_fname with final base name and orig stream name. */ + status = create_synthetic_smb_fname(talloc_tos(), final_name, + smb_fname->stream_name, NULL, + &smb_fname_final); + if (!NT_STATUS_IS_OK(status)) { + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); + goto done; + } + + /* new filename with path */ + DEBUG(10, ("recycle: recycled file name: %s\n", + smb_fname_str_dbg(smb_fname_final))); /* check if we should delete file from recycle bin */ - if (recycle_file_exist(handle, final_name)) { + if (recycle_file_exist(handle, smb_fname_final)) { if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) { - DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name)); - if (SMB_VFS_NEXT_UNLINK(handle, final_name) != 0) { + DEBUG(3, ("recycle: Removing old file %s from recycle " + "bin\n", smb_fname_str_dbg(smb_fname_final))); + if (SMB_VFS_NEXT_UNLINK(handle, + smb_fname_final) != 0) { DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno))); } } @@ -567,43 +632,41 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name) /* rename file we move to recycle bin */ i = 1; - while (recycle_file_exist(handle, final_name)) { + while (recycle_file_exist(handle, smb_fname_final)) { SAFE_FREE(final_name); if (asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base) == -1) { ALLOC_CHECK(final_name, done); } + TALLOC_FREE(smb_fname_final->base_name); + smb_fname_final->base_name = talloc_strdup(smb_fname_final, + final_name); + if (smb_fname_final->base_name == NULL) { + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); + goto done; + } } - status = create_synthetic_smb_fname_split(talloc_tos(), file_name, - NULL, &smb_fname_file); - if (!NT_STATUS_IS_OK(status)) { - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); - goto done; - } - status = create_synthetic_smb_fname_split(talloc_tos(), final_name, - NULL, &smb_fname_final); - if (!NT_STATUS_IS_OK(status)) { - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); - goto done; - } - - DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name)); - rc = SMB_VFS_NEXT_RENAME(handle, smb_fname_file, smb_fname_final); + DEBUG(10, ("recycle: Moving %s to %s\n", smb_fname_str_dbg(smb_fname), + smb_fname_str_dbg(smb_fname_final))); + rc = SMB_VFS_NEXT_RENAME(handle, smb_fname, smb_fname_final); if (rc != 0) { - DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); - rc = SMB_VFS_NEXT_UNLINK(handle, file_name); + DEBUG(3, ("recycle: Move error %d (%s), purging file %s " + "(%s)\n", errno, strerror(errno), + smb_fname_str_dbg(smb_fname), + smb_fname_str_dbg(smb_fname_final))); + rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* touch access date of moved file */ if (recycle_touch(handle) == True || recycle_touch_mtime(handle)) - recycle_do_touch(handle, final_name, recycle_touch_mtime(handle)); + recycle_do_touch(handle, smb_fname_final, + recycle_touch_mtime(handle)); done: SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); - TALLOC_FREE(smb_fname_file); TALLOC_FREE(smb_fname_final); TALLOC_FREE(repository); return rc; diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 25c5096da77..05a8b67f719 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -412,9 +412,19 @@ static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_ return ret; } -static int shadow_copy2_unlink(vfs_handle_struct *handle, const char *fname) +static int shadow_copy2_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname_in) { - SHADOW2_NEXT(UNLINK, (handle, name), int, -1); + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + SHADOW2_NEXT_SMB_FNAME(UNLINK, (handle, smb_fname), int, -1); } static int shadow_copy2_chmod(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index f1b9a504b91..dca18e09539 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -368,45 +368,6 @@ 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) -{ - struct smb_filename *smb_fname = NULL; - struct smb_filename *smb_fname_stream = NULL; - char *sname = NULL; - NTSTATUS status; - - 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; - } - - 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; - } - - 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); - - return sname; -} - static NTSTATUS walk_streams(vfs_handle_struct *handle, struct smb_filename *smb_fname_base, char **pdirname, @@ -619,25 +580,31 @@ static int streams_depot_open(vfs_handle_struct *handle, return ret; } -static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) +static int streams_depot_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { struct smb_filename *smb_fname_base = NULL; NTSTATUS status; int ret = -1; - DEBUG(10, ("streams_depot_unlink called for %s\n", fname)); + DEBUG(10, ("streams_depot_unlink called for %s\n", + smb_fname_str_dbg(smb_fname))); - if (is_ntfs_stream_name(fname)) { - char *stream_fname; + /* If there is a valid stream, just unlink the stream and return. */ + if (is_ntfs_stream_smb_fname(smb_fname) && + !is_ntfs_default_stream_smb_fname(smb_fname)) { + struct smb_filename *smb_fname_stream = NULL; - stream_fname = stream_name(handle, fname, false); - if (stream_fname == NULL) { + status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, + false); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); return -1; } - ret = SMB_VFS_NEXT_UNLINK(handle, stream_fname); + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_stream); - TALLOC_FREE(stream_fname); + TALLOC_FREE(smb_fname_stream); return ret; } @@ -645,8 +612,8 @@ 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); + 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); return -1; @@ -673,9 +640,10 @@ static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) TALLOC_FREE(dirname); } - TALLOC_FREE(smb_fname_base); + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); - return SMB_VFS_NEXT_UNLINK(handle, fname); + TALLOC_FREE(smb_fname_base); + return ret; } static int streams_depot_rename(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 49f11a22ac6..6137d01159b 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -533,36 +533,42 @@ static int streams_xattr_open(vfs_handle_struct *handle, return -1; } -static int streams_xattr_unlink(vfs_handle_struct *handle, const char *fname) +static int streams_xattr_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { NTSTATUS status; - char *base = NULL; - char *sname = NULL; int ret = -1; char *xattr_name; - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_UNLINK(handle, fname); + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); } - status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname); - if (!NT_STATUS_IS_OK(status)) { - errno = EINVAL; - goto fail; - } + /* If the default stream is requested, just open the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + struct smb_filename *smb_fname_base = NULL; + + status = copy_smb_filename(talloc_tos(), smb_fname, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_base); - if (sname == NULL){ - return SMB_VFS_NEXT_UNLINK(handle, base); + TALLOC_FREE(smb_fname_base); + return ret; } - xattr_name = talloc_asprintf(talloc_tos(), "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, sname); - if (xattr_name == NULL) { - errno = ENOMEM; + status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + &xattr_name); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); goto fail; } - ret = SMB_VFS_REMOVEXATTR(handle->conn, base, xattr_name); + ret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname->base_name, xattr_name); if ((ret == -1) && (errno == ENOATTR)) { errno = ENOENT; @@ -572,8 +578,7 @@ static int streams_xattr_unlink(vfs_handle_struct *handle, const char *fname) ret = 0; fail: - TALLOC_FREE(base); - TALLOC_FREE(sname); + TALLOC_FREE(xattr_name); return ret; } diff --git a/source3/modules/vfs_syncops.c b/source3/modules/vfs_syncops.c index ff210e695b7..91345e1cad8 100644 --- a/source3/modules/vfs_syncops.c +++ b/source3/modules/vfs_syncops.c @@ -107,7 +107,7 @@ static void syncops_name(const char *name) /* sync two meta data changes for 1 names */ -static void syncops_smb_fname(struct smb_filename *smb_fname) +static void syncops_smb_fname(const struct smb_filename *smb_fname) { char *parent; parent = parent_dir(NULL, smb_fname->base_name); @@ -166,9 +166,10 @@ static int syncops_open(vfs_handle_struct *handle, (handle, smb_fname, fsp, flags, mode)); } -static int syncops_unlink(vfs_handle_struct *handle, const char *fname) +static int syncops_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SYNCOPS_NEXT(UNLINK, fname, (handle, fname)); + SYNCOPS_NEXT_SMB_FNAME(UNLINK, smb_fname, (handle, smb_fname)); } static int syncops_mknod(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index 39adfdfe158..e805fbcb2c1 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -611,27 +611,35 @@ static bool xattr_tdb_init(int snum, struct db_context **p_db) /* * On unlink we need to delete the tdb record */ -static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path) +static int xattr_tdb_unlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname_tmp = NULL; struct file_id id; struct db_context *db; struct db_record *rec; - int ret; + NTSTATUS status; + int ret = -1; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); return -1; } - ret = SMB_VFS_NEXT_UNLINK(handle, path); + if (SMB_VFS_STAT(handle->conn, smb_fname_tmp) == -1) { + goto out; + } + + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); if (ret == -1) { - return -1; + goto out; } - id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf); + id = SMB_VFS_FILE_ID_CREATE(handle->conn, &smb_fname_tmp->st); rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id); @@ -644,7 +652,9 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path) TALLOC_FREE(rec); } - return 0; + out: + TALLOC_FREE(smb_fname_tmp); + return ret; } /* diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ad21cf1d400..537394c4812 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -217,31 +217,32 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) for (i=0; iconn; bool delete_file = false; bool changed_user = false; - struct share_mode_lock *lck; - SMB_STRUCT_STAT sbuf; + struct share_mode_lock *lck = NULL; + struct smb_filename *smb_fname = NULL; + char *fname = NULL; NTSTATUS status = NT_STATUS_OK; int ret; struct file_id id; + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + /* * Lock the share entries, and determine if we should delete * on close. If so delete whilst the lock is still in effect. @@ -276,8 +284,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " - "lock for file %s\n", fsp->fsp_name)); - return NT_STATUS_INVALID_PARAMETER; + "lock for file %s\n", smb_fname_str_dbg(smb_fname))); + status = NT_STATUS_INVALID_PARAMETER; + goto done; } if (fsp->write_time_forced) { @@ -286,7 +295,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (!del_share_mode(lck, fsp)) { DEBUG(0, ("close_remove_share_mode: Could not delete share " - "entry for file %s\n", fsp->fsp_name)); + "entry for file %s\n", + smb_fname_str_dbg(smb_fname))); } if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) { @@ -344,7 +354,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, */ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "- deleting file.\n", fsp->fsp_name)); + "- deleting file.\n", smb_fname_str_dbg(smb_fname))); /* * Don't try to update the write time when we delete the file @@ -356,7 +366,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. " "Change user to uid %u\n", - fsp->fsp_name, + smb_fname_str_dbg(smb_fname), (unsigned int)lck->delete_token->uid)); if (!push_sec_ctx()) { @@ -377,30 +387,30 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, hasn't been renamed. */ if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf); + ret = SMB_VFS_LSTAT(conn, smb_fname); } else { - ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf); + ret = SMB_VFS_STAT(conn, smb_fname); } if (ret != 0) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and stat failed with error %s\n", - fsp->fsp_name, strerror(errno) )); + smb_fname_str_dbg(smb_fname), strerror(errno))); /* * Don't save the errno here, we ignore this error */ goto done; } - id = vfs_file_id_from_sbuf(conn, &sbuf); + id = vfs_file_id_from_sbuf(conn, &smb_fname->st); if (!file_id_equal(&fsp->file_id, &id)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and dev and/or inode does not match\n", - fsp->fsp_name )); + smb_fname_str_dbg(smb_fname))); DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, " "stat file_id %s\n", - fsp->fsp_name, + smb_fname_str_dbg(smb_fname), file_id_string_tos(&fsp->file_id), file_id_string_tos(&id))); /* @@ -410,9 +420,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } if ((conn->fs_capabilities & FILE_NAMED_STREAMS) - && !is_ntfs_stream_name(fsp->fsp_name)) { + && !is_ntfs_stream_smb_fname(smb_fname)) { - status = delete_all_streams(conn, fsp->fsp_name); + status = delete_all_streams(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_all_streams failed: %s\n", @@ -422,7 +432,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } - if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + if (SMB_VFS_UNLINK(conn, smb_fname) != 0) { /* * This call can potentially fail as another smbd may * have had the file open with delete on close set and @@ -433,14 +443,21 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and unlink failed with error %s\n", - fsp->fsp_name, strerror(errno) )); + smb_fname_str_dbg(smb_fname), strerror(errno))); status = map_nt_error_from_unix(errno); } + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_FILE_NAME, - fsp->fsp_name); + fname); + + TALLOC_FREE(fname); /* As we now have POSIX opens which can unlink * with other open files we may have taken @@ -459,6 +476,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } TALLOC_FREE(lck); + TALLOC_FREE(smb_fname); return status; } @@ -637,10 +655,17 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, enum file_close_type close_type) { - struct share_mode_lock *lck = 0; + struct share_mode_lock *lck = NULL; + struct smb_filename *smb_dname = NULL; bool delete_dir = False; NTSTATUS status = NT_STATUS_OK; + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + NULL, &smb_dname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + /* * NT can set delete_on_close of the last open * reference to a directory also. @@ -650,12 +675,15 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, NULL); if (lck == NULL) { - DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); - return NT_STATUS_INVALID_PARAMETER; + DEBUG(0, ("close_directory: Could not get share mode lock for " + "%s\n", smb_fname_str_dbg(smb_dname))); + status = NT_STATUS_INVALID_PARAMETER; + goto out; } if (!del_share_mode(lck, fsp)) { - DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); + DEBUG(0, ("close_directory: Could not delete share entry for " + "%s\n", smb_fname_str_dbg(smb_dname))); } if (fsp->initial_delete_on_close) { @@ -712,12 +740,11 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, TALLOC_FREE(lck); - status = rmdir_internals(talloc_tos(), - fsp->conn, fsp->fsp_name); + status = rmdir_internals(talloc_tos(), fsp->conn, smb_dname); DEBUG(5,("close_directory: %s. Delete on close was set - " "deleting directory returned %s.\n", - fsp->fsp_name, nt_errstr(status))); + smb_fname_str_dbg(smb_dname), nt_errstr(status))); /* unbecome user. */ pop_sec_ctx(); @@ -740,7 +767,8 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n", - fsp->fsp_name, fsp->fh->fd, errno, strerror(errno))); + smb_fname_str_dbg(smb_dname), fsp->fh->fd, errno, + strerror(errno))); } /* @@ -748,6 +776,10 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, */ close_filestruct(fsp); file_free(req, fsp); + + out: + TALLOC_FREE(lck); + TALLOC_FREE(smb_dname); return status; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e6f877cfbb1..d40b8a89028 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1415,9 +1415,22 @@ bool create_msdfs_link(const struct junction_map *jucn) if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { if (errno == EEXIST) { - if(SMB_VFS_UNLINK(conn,path)!=0) { + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = create_synthetic_smb_fname(talloc_tos(), path, + NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); goto out; } + + if(SMB_VFS_UNLINK(conn, smb_fname)!=0) { + TALLOC_FREE(smb_fname); + goto out; + } + TALLOC_FREE(smb_fname); } if (SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { DEBUG(1,("create_msdfs_link: symlink failed " @@ -1441,15 +1454,26 @@ bool remove_msdfs_link(const struct junction_map *jucn) char *cwd; connection_struct *conn; bool ret = False; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; if (!junction_to_local_path(jucn, &path, &conn, &cwd)) { return false; } - if( SMB_VFS_UNLINK(conn, path) == 0 ) { + status = create_synthetic_smb_fname(talloc_tos(), path, + NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return false; + } + + if( SMB_VFS_UNLINK(conn, smb_fname) == 0 ) { ret = True; } + TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); conn_free_internal(conn); return ret; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f9dc58311c1..d7eaaa8a2c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5245,35 +5245,39 @@ void reply_mkdir(struct smb_request *req) static bool recursive_rmdir(TALLOC_CTX *ctx, connection_struct *conn, - char *directory) + struct smb_filename *smb_dname) { const char *dname = NULL; bool ret = True; long offset = 0; SMB_STRUCT_STAT st; - struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory, - NULL, 0); + struct smb_Dir *dir_hnd; + SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); + + dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0); if(dir_hnd == NULL) return False; while((dname = ReadDirName(dir_hnd, &offset, &st))) { + struct smb_filename *smb_dname_full = NULL; char *fullname = NULL; - struct smb_filename *smb_fname = NULL; + bool do_break = true; NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { continue; } - if (!is_visible_file(conn, directory, dname, &st, False)) { + if (!is_visible_file(conn, smb_dname->base_name, dname, &st, + false)) { continue; } /* Construct the full name. */ fullname = talloc_asprintf(ctx, "%s/%s", - directory, + smb_dname->base_name, dname); if (!fullname) { errno = ENOMEM; @@ -5281,33 +5285,38 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, } status = create_synthetic_smb_fname(talloc_tos(), fullname, - NULL, NULL, &smb_fname); + NULL, NULL, + &smb_dname_full); if (!NT_STATUS_IS_OK(status)) { goto err_break; } - if(SMB_VFS_LSTAT(conn, smb_fname) != 0) { + if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { goto err_break; } - if(smb_fname->st.st_ex_mode & S_IFDIR) { - if(!recursive_rmdir(ctx, conn, fullname)) { + if(smb_dname_full->st.st_ex_mode & S_IFDIR) { + if(!recursive_rmdir(ctx, conn, smb_dname_full)) { goto err_break; } - if(SMB_VFS_RMDIR(conn,fullname) != 0) { + if(SMB_VFS_RMDIR(conn, + smb_dname_full->base_name) != 0) { goto err_break; } - } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { + } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) { goto err_break; } - TALLOC_FREE(smb_fname); - TALLOC_FREE(fullname); - continue; + + /* Successful iteration. */ + do_break = false; + err_break: - TALLOC_FREE(smb_fname); + TALLOC_FREE(smb_dname_full); TALLOC_FREE(fullname); - ret = false; - break; + if (do_break) { + ret = false; + break; + } } TALLOC_FREE(dir_hnd); return ret; @@ -5318,33 +5327,35 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, ****************************************************************************/ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, - connection_struct *conn, - const char *directory) + connection_struct *conn, + struct smb_filename *smb_dname) { int ret; SMB_STRUCT_STAT st; + SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); + /* Might be a symlink. */ - if(vfs_lstat_smb_fname(conn, directory, &st) != 0) { + if(SMB_VFS_LSTAT(conn, smb_dname) != 0) { return map_nt_error_from_unix(errno); } - if (S_ISLNK(st.st_ex_mode)) { + if (S_ISLNK(smb_dname->st.st_ex_mode)) { /* Is what it points to a directory ? */ - if(vfs_stat_smb_fname(conn, directory, &st) != 0) { + if(SMB_VFS_STAT(conn, smb_dname) != 0) { return map_nt_error_from_unix(errno); } - if (!(S_ISDIR(st.st_ex_mode))) { + if (!(S_ISDIR(smb_dname->st.st_ex_mode))) { return NT_STATUS_NOT_A_DIRECTORY; } - ret = SMB_VFS_UNLINK(conn,directory); + ret = SMB_VFS_UNLINK(conn, smb_dname); } else { - ret = SMB_VFS_RMDIR(conn,directory); + ret = SMB_VFS_RMDIR(conn, smb_dname->base_name); } if (ret == 0) { notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, - directory); + smb_dname->base_name); return NT_STATUS_OK; } @@ -5358,7 +5369,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, const char *dname; long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, - directory, NULL, 0); + smb_dname->base_name, NULL, + 0); if(dir_hnd == NULL) { errno = ENOTEMPTY; @@ -5368,7 +5380,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) { if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) continue; - if (!is_visible_file(conn, directory, dname, &st, False)) + if (!is_visible_file(conn, smb_dname->base_name, dname, + &st, false)) continue; if(!IS_VETO_PATH(conn, dname)) { TALLOC_FREE(dir_hnd); @@ -5389,56 +5402,80 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, /* Do a recursive delete. */ RewindDir(dir_hnd,&dirpos); while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) { + struct smb_filename *smb_dname_full = NULL; char *fullname = NULL; + bool do_break = true; + NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { continue; } - if (!is_visible_file(conn, directory, dname, &st, False)) { + if (!is_visible_file(conn, smb_dname->base_name, dname, + &st, false)) { continue; } fullname = talloc_asprintf(ctx, "%s/%s", - directory, + smb_dname->base_name, dname); if(!fullname) { errno = ENOMEM; - break; + goto err_break; } - if(vfs_lstat_smb_fname(conn,fullname, &st) != 0) { - break; + status = create_synthetic_smb_fname(talloc_tos(), + fullname, NULL, + NULL, + &smb_dname_full); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto err_break; } - if(st.st_ex_mode & S_IFDIR) { - if(!recursive_rmdir(ctx, conn, fullname)) { - break; + + if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { + goto err_break; + } + if(smb_dname_full->st.st_ex_mode & S_IFDIR) { + if(!recursive_rmdir(ctx, conn, + smb_dname_full)) { + goto err_break; } - if(SMB_VFS_RMDIR(conn,fullname) != 0) { - break; + if(SMB_VFS_RMDIR(conn, + smb_dname_full->base_name) != 0) { + goto err_break; } - } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { - break; + } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) { + goto err_break; } + + /* Successful iteration. */ + do_break = false; + + err_break: TALLOC_FREE(fullname); + TALLOC_FREE(smb_dname_full); + if (do_break) + break; } TALLOC_FREE(dir_hnd); /* Retry the rmdir */ - ret = SMB_VFS_RMDIR(conn,directory); + ret = SMB_VFS_RMDIR(conn, smb_dname->base_name); } err: if (ret != 0) { DEBUG(3,("rmdir_internals: couldn't remove directory %s : " - "%s\n", directory,strerror(errno))); + "%s\n", smb_fname_str_dbg(smb_dname), + strerror(errno))); return map_nt_error_from_unix(errno); } notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, - directory); + smb_dname->base_name); return NT_STATUS_OK; } @@ -5480,7 +5517,7 @@ void reply_rmdir(struct smb_request *req) } dptr_closepath(directory, req->smbpid); - status = rmdir_internals(ctx, conn, directory); + status = rmdir_internals(ctx, conn, smb_dname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); goto out; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d8a78e339ed..a6440d574f2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1160,7 +1160,7 @@ static uint32 unix_filetype(mode_t mode) enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR}; static NTSTATUS unix_perms_from_wire( connection_struct *conn, - SMB_STRUCT_STAT *psbuf, + const SMB_STRUCT_STAT *psbuf, uint32 perms, enum perm_type ptype, mode_t *ret_perms) @@ -5082,13 +5082,13 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, static NTSTATUS smb_set_file_size(connection_struct *conn, struct smb_request *req, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf, - SMB_OFF_T size) + files_struct *fsp, + const struct smb_filename *smb_fname, + const SMB_STRUCT_STAT *psbuf, + SMB_OFF_T size) { - struct smb_filename *smb_fname = NULL; NTSTATUS status = NT_STATUS_OK; + struct smb_filename *smb_fname_tmp = NULL; files_struct *new_fsp = NULL; if (!VALID_STAT(*psbuf)) { @@ -5102,7 +5102,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, } DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n", - fname, (double)size )); + smb_fname_str_dbg(smb_fname), (double)size)); if (fsp && fsp->fh->fd != -1) { /* Handle based call. */ @@ -5113,17 +5113,18 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, return NT_STATUS_OK; } - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); + status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp); if (!NT_STATUS_IS_OK(status)) { return status; } + smb_fname_tmp->st = *psbuf; + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ 0, /* root_dir_fid */ - smb_fname, /* fname */ + smb_fname_tmp, /* fname */ FILE_WRITE_ATTRIBUTES, /* access_mask */ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */ FILE_SHARE_DELETE), @@ -5137,8 +5138,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, &new_fsp, /* result */ NULL); /* pinfo */ - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); + TALLOC_FREE(smb_fname_tmp); if (!NT_STATUS_IS_OK(status)) { /* NB. We check for open_was_deferred in the caller. */ @@ -5998,8 +5998,7 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { SMB_OFF_T size; @@ -6017,12 +6016,13 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, } #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for " - "file %s to %.0f\n", fname, (double)size )); + "file %s to %.0f\n", smb_fname_str_dbg(smb_fname), + (double)size)); return smb_set_file_size(conn, req, fsp, - fname, - psbuf, + smb_fname, + &smb_fname->st, size); } @@ -6033,8 +6033,7 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, static NTSTATUS smb_unix_mknod(connection_struct *conn, const char *pdata, int total_data, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { uint32 file_type = IVAL(pdata,56); #if defined(HAVE_MAKEDEV) @@ -6050,7 +6049,8 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode); + status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, + PERM_NEW_FILE, &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6084,11 +6084,12 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ -0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname )); + DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev " + "%.0f mode 0%o for file %s\n", (double)dev, + (unsigned int)unixmode, smb_fname_str_dbg(smb_fname))); /* Ok - do the mknod. */ - if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) { + if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) { return map_nt_error_from_unix(errno); } @@ -6098,18 +6099,15 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn, if (lp_inherit_perms(SNUM(conn))) { char *parent; - if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) { + if (!parent_dirname(talloc_tos(), smb_fname->base_name, + &parent, NULL)) { return NT_STATUS_NO_MEMORY; } - inherit_access_posix_acl(conn, parent, fname, unixmode); + inherit_access_posix_acl(conn, parent, smb_fname->base_name, + unixmode); TALLOC_FREE(parent); } - if (vfs_stat_smb_fname(conn, fname, psbuf) != 0) { - status = map_nt_error_from_unix(errno); - SMB_VFS_UNLINK(conn,fname); - return status; - } return NT_STATUS_OK; } @@ -6122,8 +6120,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { struct smb_file_time ft; uint32 raw_unixmode; @@ -6137,6 +6134,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, files_struct *all_fsps = NULL; bool modify_mtime = true; struct file_id id; + SMB_STRUCT_STAT sbuf; ZERO_STRUCT(ft); @@ -6163,8 +6161,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, set_grp = (gid_t)IVAL(pdata,48); raw_unixmode = IVAL(pdata,84); - if (VALID_STAT(*psbuf)) { - if (S_ISDIR(psbuf->st_ex_mode)) { + if (VALID_STAT(smb_fname->st)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { ptype = PERM_EXISTING_DIR; } else { ptype = PERM_EXISTING_FILE; @@ -6173,16 +6171,22 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, ptype = PERM_NEW_FILE; } - status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode); + status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, + ptype, &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; } - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \ -size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", - fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode)); + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = " + "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", + smb_fname_str_dbg(smb_fname), (double)size, + (unsigned int)set_owner, (unsigned int)set_grp, + (int)raw_unixmode)); - if (!VALID_STAT(*psbuf)) { + sbuf = smb_fname->st; + + if (!VALID_STAT(sbuf)) { + struct smb_filename *smb_fname_tmp = NULL; /* * The only valid use of this is to create character and block * devices, and named pipes. This is deprecated (IMHO) and @@ -6192,17 +6196,32 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", status = smb_unix_mknod(conn, pdata, total_data, - fname, - psbuf); + smb_fname); if (!NT_STATUS_IS_OK(status)) { return status; } + status = copy_smb_filename(talloc_tos(), smb_fname, + &smb_fname_tmp); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) { + status = map_nt_error_from_unix(errno); + TALLOC_FREE(smb_fname_tmp); + SMB_VFS_UNLINK(conn, smb_fname); + return status; + } + + sbuf = smb_fname_tmp->st; + TALLOC_FREE(smb_fname_tmp); + /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; - size = get_file_size_stat(psbuf); - ft.atime = psbuf->st_ex_atime; - ft.mtime = psbuf->st_ex_mtime; + size = get_file_size_stat(&sbuf); + ft.atime = sbuf.st_ex_atime; + ft.mtime = sbuf.st_ex_mtime; /* * We continue here as we might want to change the * owner uid/gid. @@ -6216,7 +6235,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * */ if (!size) { - size = get_file_size_stat(psbuf); + size = get_file_size_stat(&sbuf); } #endif @@ -6225,9 +6244,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", */ if (raw_unixmode != SMB_MODE_NO_CHANGE) { - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", - (unsigned int)unixmode, fname )); - if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) { + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " + "setting mode 0%o for file %s\n", + (unsigned int)unixmode, + smb_fname_str_dbg(smb_fname))); + if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) { return map_nt_error_from_unix(errno); } } @@ -6236,22 +6257,27 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Deal with the UNIX specific uid set. */ - if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) { + if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && + (sbuf.st_ex_uid != set_owner)) { int ret; - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n", - (unsigned int)set_owner, fname )); + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " + "changing owner %u for path %s\n", + (unsigned int)set_owner, + smb_fname_str_dbg(smb_fname))); - if (S_ISLNK(psbuf->st_ex_mode)) { - ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1); + if (S_ISLNK(sbuf.st_ex_mode)) { + ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, + set_owner, (gid_t)-1); } else { - ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1); + ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, + set_owner, (gid_t)-1); } if (ret != 0) { status = map_nt_error_from_unix(errno); if (delete_on_fail) { - SMB_VFS_UNLINK(conn,fname); + SMB_VFS_UNLINK(conn, smb_fname); } return status; } @@ -6261,13 +6287,17 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Deal with the UNIX specific gid set. */ - if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) { - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", - (unsigned int)set_owner, fname )); - if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) { + if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && + (sbuf.st_ex_gid != set_grp)) { + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " + "changing group %u for file %s\n", + (unsigned int)set_owner, + smb_fname_str_dbg(smb_fname))); + if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1, + set_grp) != 0) { status = map_nt_error_from_unix(errno); if (delete_on_fail) { - SMB_VFS_UNLINK(conn,fname); + SMB_VFS_UNLINK(conn, smb_fname); } return status; } @@ -6276,10 +6306,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Deal with any size changes. */ status = smb_set_file_size(conn, req, - fsp, - fname, - psbuf, - size); + fsp, + smb_fname, + &sbuf, + size); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6313,8 +6343,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", status = smb_set_file_time(conn, fsp, - fname, - psbuf, + smb_fname->base_name, + &sbuf, &ft, false); if (modify_mtime) { @@ -6333,8 +6363,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { NTSTATUS status; uint32 smb_fflags; @@ -6348,7 +6377,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, * and UNIX_INFO2. */ status = smb_set_file_unix_basic(conn, req, pdata, total_data, - fsp, fname, psbuf); + fsp, smb_fname); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6362,8 +6391,8 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, if (smb_fmask != 0) { int stat_fflags = 0; - if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask, - &stat_fflags)) { + if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags, + smb_fmask, &stat_fflags)) { /* Client asked to alter a flag we don't understand. */ return NT_STATUS_INVALID_PARAMETER; } @@ -6372,7 +6401,8 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, /* XXX: we should be using SMB_VFS_FCHFLAGS here. */ return NT_STATUS_NOT_SUPPORTED; } else { - if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) { + if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name, + stat_fflags) != 0) { return map_nt_error_from_unix(errno); } } @@ -7078,8 +7108,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } @@ -7137,8 +7166,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } @@ -7148,8 +7176,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 9585d6d226e..e6a3940f4f2 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -366,7 +366,17 @@ static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg if (strcmp("rmdir", argv[0]) == 0 ) { ret = SMB_VFS_RMDIR(vfs->conn, argv[1]); } else if (strcmp("unlink", argv[0]) == 0 ) { - ret = SMB_VFS_UNLINK(vfs->conn, argv[1]); + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = create_synthetic_smb_fname_split(mem_ctx, argv[1], + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + ret = SMB_VFS_UNLINK(vfs->conn, smb_fname); + TALLOC_FREE(smb_fname); } else if (strcmp("chdir", argv[0]) == 0 ) { ret = SMB_VFS_CHDIR(vfs->conn, argv[1]); } else { -- 2.34.1