From 258952aa85f2a68e2d2362522f6114c6a439f1e3 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 2 Jul 2009 09:27:44 -0700 Subject: s3: Plumb smb_filename through SMB_VFS_UNLINK --- source3/smbd/close.c | 102 ++++++++++++++++++---------- source3/smbd/msdfs.c | 28 +++++++- source3/smbd/reply.c | 127 ++++++++++++++++++++++------------- source3/smbd/trans2.c | 183 +++++++++++++++++++++++++++++--------------------- 4 files changed, 280 insertions(+), 160 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index ad21cf1d40..537394c481 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 e6f877cfbb..d40b8a8902 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 f9dc58311c..d7eaaa8a2c 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 d8a78e339e..a6440d574f 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; } -- cgit