From 3cb0e521e1bdddde972b6fd08fb86f7fe73da8d5 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 2 Jul 2009 13:39:20 -0700 Subject: s3: Plumb smb_filename through SMB_VFS_NTIMES --- examples/VFS/skel_opaque.c | 6 +- examples/VFS/skel_transparent.c | 6 +- source3/include/proto.h | 7 +- source3/include/vfs.h | 6 +- source3/modules/onefs_streams.c | 37 ++++++--- source3/modules/vfs_cap.c | 26 +++++- source3/modules/vfs_default.c | 20 +++-- source3/modules/vfs_full_audit.c | 8 +- source3/modules/vfs_onefs.c | 5 +- source3/modules/vfs_onefs_shadow_copy.c | 9 ++- source3/modules/vfs_recycle.c | 11 +-- source3/modules/vfs_shadow_copy2.c | 14 +++- source3/smbd/close.c | 35 ++++---- source3/smbd/dosmode.c | 18 +---- source3/smbd/reply.c | 56 ++++++------- source3/smbd/trans2.c | 136 +++++++++++++++----------------- source3/torture/cmd_vfs.c | 14 +++- 17 files changed, 238 insertions(+), 176 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 54f7ce8cf2..a0cb533eb8 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -237,9 +237,11 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return vfswrap_getwd(NULL, buf); } -static int skel_ntimes(vfs_handle_struct *handle, const char *path, struct smb_file_time *ft) +static int skel_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct smb_file_time *ft) { - return vfswrap_ntimes(NULL, path, ft); + return vfswrap_ntimes(NULL, smb_fname, ft); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset) diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 09a926ad43..cce1d13d8d 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -230,9 +230,11 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return SMB_VFS_NEXT_GETWD(handle, buf); } -static int skel_ntimes(vfs_handle_struct *handle, const char *path, struct smb_file_time *ft) +static int skel_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct smb_file_time *ft) { - return SMB_VFS_NEXT_NTIMES(handle, path, ft); + return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset) diff --git a/source3/include/proto.h b/source3/include/proto.h index 6bd37efc57..dfcb38d22d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6241,8 +6241,8 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode); uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf); int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, uint32 dosmode, const char *parent_dir, bool newfile); -int file_ntimes(connection_struct *conn, const char *fname, - struct smb_file_time *ft, const SMB_STRUCT_STAT *psbuf); +int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname, + struct smb_file_time *ft); bool set_sticky_write_time_path(struct file_id fileid, const struct timespec mtime); bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime); @@ -7047,8 +7047,7 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, const struct smb_filename *smb_fname_new); NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, - const char *fname, - const SMB_STRUCT_STAT *psbuf, + const struct smb_filename *smb_fname, struct smb_file_time *ft, bool setting_write_time); void reply_findclose(struct smb_request *req); diff --git a/source3/include/vfs.h b/source3/include/vfs.h index cfa3403e82..91bda47ac6 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_UNLINK. */ + SMB_VFS_RENAME, SMB_VFS_UNLINK, SMB_VFS_NTIMES. */ #define SMB_VFS_INTERFACE_VERSION 26 @@ -375,7 +375,9 @@ struct vfs_ops { int (*lchown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid); int (*chdir)(struct vfs_handle_struct *handle, const char *path); char *(*getwd)(struct vfs_handle_struct *handle, char *buf); - int (*ntimes)(struct vfs_handle_struct *handle, const char *path, struct smb_file_time *ft); + int (*ntimes)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct smb_file_time *ft); int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_OFF_T offset); bool (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 share_mode); diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index 2a31036862..2be490f52d 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -508,15 +508,15 @@ int onefs_unlink(vfs_handle_struct *handle, return ret; } -int onefs_vtimes_streams(vfs_handle_struct *handle, const char *fname, +int onefs_vtimes_streams(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, int flags, struct timespec times[3]) { + struct smb_filename *smb_fname_onefs = NULL; int ret; - bool is_stream; - char *base; - char *stream; int dirfd; int saved_errno; + NTSTATUS status; START_PROFILE(syscall_ntimes); @@ -524,23 +524,40 @@ int onefs_vtimes_streams(vfs_handle_struct *handle, const char *fname, if (ret) return ret; - if (!is_stream) { - ret = vtimes(fname, times, flags); + if (!is_ntfs_stream_smb_fname(smb_fname)) { + ret = vtimes(smb_fname->base_name, times, flags); return ret; } - dirfd = get_stream_dir_fd(handle->conn, base, NULL); - if (dirfd < -1) { + 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; } - ret = enc_vtimesat(dirfd, stream, ENC_DEFAULT, times, flags); + /* Default stream (the ::$DATA was just stripped off). */ + if (!is_ntfs_stream_smb_fname(smb_fname_onefs)) { + ret = vtimes(smb_fname_onefs->base_name, times, flags); + goto out; + } + + dirfd = get_stream_dir_fd(handle->conn, smb_fname->base_name, NULL); + if (dirfd < -1) { + ret = -1; + goto out; + } - END_PROFILE(syscall_ntimes); + ret = enc_vtimesat(dirfd, smb_fname_onefs->stream_name, ENC_DEFAULT, + times, flags); saved_errno = errno; close(dirfd); errno = saved_errno; + + out: + END_PROFILE(syscall_ntimes); + TALLOC_FREE(smb_fname_onefs); return ret; } diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 9348ab9554..7e363b6be7 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -301,16 +301,36 @@ static int cap_chdir(vfs_handle_struct *handle, const char *path) return SMB_VFS_NEXT_CHDIR(handle, cappath); } -static int cap_ntimes(vfs_handle_struct *handle, const char *path, +static int cap_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, struct smb_file_time *ft) { - 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_NTIMES(handle, cappath, ft); + + /* 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_NTIMES(handle, smb_fname_tmp, ft); + + TALLOC_FREE(smb_fname_tmp); + return ret; } diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index c95c68fe0f..7565e7bb65 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -789,34 +789,42 @@ static char *vfswrap_getwd(vfs_handle_struct *handle, char *path) system will support. **********************************************************************/ -static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, +static int vfswrap_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, struct smb_file_time *ft) { - int result; + int result = -1; START_PROFILE(syscall_ntimes); + + if (smb_fname->stream_name) { + errno = ENOENT; + goto out; + } + #if defined(HAVE_UTIMES) if (ft != NULL) { struct timeval tv[2]; tv[0] = convert_timespec_to_timeval(ft->atime); tv[1] = convert_timespec_to_timeval(ft->mtime); - result = utimes(path, tv); + result = utimes(smb_fname->base_name, tv); } else { - result = utimes(path, NULL); + result = utimes(smb_fname->base_name, NULL); } #elif defined(HAVE_UTIME) if (ft != NULL) { struct utimbuf times; times.actime = convert_timespec_to_time_t(ft->atime); times.modtime = convert_timespec_to_time_t(ft->mtime); - result = utime(path, ×); + result = utime(smb_fname->base_name, ×); } else { - result = utime(path, NULL); + result = utime(smb_fname->base_name, NULL); } #else errno = ENOSYS; result = -1; #endif + out: END_PROFILE(syscall_ntimes); return result; } diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 1f5e8333b9..e8702aa2c8 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1011,13 +1011,15 @@ static char *smb_full_audit_getwd(vfs_handle_struct *handle, } static int smb_full_audit_ntimes(vfs_handle_struct *handle, - const char *path, struct smb_file_time *ft) + const struct smb_filename *smb_fname, + struct smb_file_time *ft) { int result; - result = SMB_VFS_NEXT_NTIMES(handle, path, ft); + result = SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft); - do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", path); + do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", + smb_fname_str_do_log(smb_fname)); return result; } diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c index 8ca3795e27..1a37622bea 100644 --- a/source3/modules/vfs_onefs.c +++ b/source3/modules/vfs_onefs.c @@ -200,7 +200,8 @@ done: return result; } -static int onefs_ntimes(vfs_handle_struct *handle, const char *fname, +static int onefs_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, struct smb_file_time *ft) { int flags = 0; @@ -230,7 +231,7 @@ static int onefs_ntimes(vfs_handle_struct *handle, const char *fname, ft->create_time.tv_nsec)); } - return onefs_vtimes_streams(handle, fname, flags, times); + return onefs_vtimes_streams(handle, smb_fname, flags, times); } static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle) diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c index 1a43e0671a..651e20a875 100644 --- a/source3/modules/vfs_onefs_shadow_copy.c +++ b/source3/modules/vfs_onefs_shadow_copy.c @@ -394,12 +394,13 @@ onefs_shadow_copy_chdir(vfs_handle_struct *handle, const char *path) } static int -onefs_shadow_copy_ntimes(vfs_handle_struct *handle, const char *path, +onefs_shadow_copy_ntimes(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, struct smb_file_time *ft) { - SHADOW_NEXT(NTIMES, - (handle, cpath ?: path, ft), - int); + SHADOW_NEXT_SMB_FNAME_CONST(NTIMES, + (handle, smb_fname_tmp, ft), + int); } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 24166d1266..771189ca73 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -417,7 +417,6 @@ static void recycle_do_touch(vfs_handle_struct *handle, { struct smb_filename *smb_fname_tmp = NULL; struct smb_file_time ft; - char *fname = NULL; NTSTATUS status; int ret, err; @@ -438,22 +437,16 @@ static void recycle_do_touch(vfs_handle_struct *handle, /* 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); + ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, &ft); err = errno; unbecome_root(); if (ret == -1 ) { DEBUG(0, ("recycle: touching %s failed, reason = %s\n", smb_fname_str_dbg(smb_fname_tmp), strerror(err))); } - out: - TALLOC_FREE(fname); + TALLOC_FREE(smb_fname_tmp); } /** diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 05a8b67f71..1f300a055c 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -446,9 +446,19 @@ static int shadow_copy2_chdir(vfs_handle_struct *handle, } static int shadow_copy2_ntimes(vfs_handle_struct *handle, - const char *fname, struct smb_file_time *ft) + const struct smb_filename *smb_fname_in, + struct smb_file_time *ft) { - SHADOW2_NEXT(NTIMES, (handle, name, ft), 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(NTIMES, (handle, smb_fname, ft), int, -1); } static int shadow_copy2_readlink(vfs_handle_struct *handle, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 537394c481..a0672f3949 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -499,12 +499,11 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts) static NTSTATUS update_write_time_on_close(struct files_struct *fsp) { - SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname = NULL; struct smb_file_time ft; NTSTATUS status; int ret = -1; - ZERO_STRUCT(sbuf); ZERO_STRUCT(ft); if (!fsp->update_write_time_on_close) { @@ -515,36 +514,44 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) fsp->close_write_time = timespec_current(); } + /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */ + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); } else { if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(fsp->conn, fsp->fsp_name, - &sbuf); + ret = SMB_VFS_LSTAT(fsp->conn, smb_fname); } else { - ret = vfs_stat_smb_fname(fsp->conn, fsp->fsp_name, - &sbuf); + ret = SMB_VFS_STAT(fsp->conn, smb_fname); } } if (ret == -1) { - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } - if (!VALID_STAT(sbuf)) { + if (!VALID_STAT(smb_fname->st)) { /* if it doesn't seem to be a real file */ - return NT_STATUS_OK; + status = NT_STATUS_OK; + goto out; } ft.mtime = fsp->close_write_time; - status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, - &sbuf, &ft, true); + status = smb_set_file_time(fsp->conn, fsp, smb_fname, &ft, true); if (!NT_STATUS_IS_OK(status)) { - return status; + goto out; } - return NT_STATUS_OK; + out: + TALLOC_FREE(smb_fname); + return status; } static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 97d788218d..76034db164 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -722,11 +722,9 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, than POSIX. *******************************************************************/ -int file_ntimes(connection_struct *conn, const char *fname, - struct smb_file_time *ft, const SMB_STRUCT_STAT *psbuf) +int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname, + struct smb_file_time *ft) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; int ret = -1; errno = 0; @@ -749,7 +747,7 @@ int file_ntimes(connection_struct *conn, const char *fname, return 0; } - if(SMB_VFS_NTIMES(conn, fname, ft) == 0) { + if(SMB_VFS_NTIMES(conn, smb_fname, ft) == 0) { return 0; } @@ -767,21 +765,13 @@ int file_ntimes(connection_struct *conn, const char *fname, (as DOS does). */ - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - - if (!NT_STATUS_IS_OK(status)) { - return -1; - } - /* Check if we have write access. */ if (can_write_to_file(conn, smb_fname)) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = SMB_VFS_NTIMES(conn, fname, ft); + ret = SMB_VFS_NTIMES(conn, smb_fname, ft); unbecome_root(); } - TALLOC_FREE(smb_fname); return ret; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 4a5610e5e1..8700146859 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1179,7 +1179,7 @@ void reply_setatr(struct smb_request *req) req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &smb_fname, - &fname); + NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1190,7 +1190,8 @@ void reply_setatr(struct smb_request *req) goto out; } - if (fname[0] == '.' && fname[1] == '\0') { + if (smb_fname->base_name[0] == '.' && + smb_fname->base_name[1] == '\0') { /* * Not sure here is the right place to catch this * condition. Might be moved to somewhere else later -- vl @@ -1203,8 +1204,7 @@ void reply_setatr(struct smb_request *req) mtime = srv_make_unix_date3(req->vwv+1); ft.mtime = convert_time_t_to_timespec(mtime); - status = smb_set_file_time(conn, NULL, fname, - &smb_fname->st, &ft, true); + status = smb_set_file_time(conn, NULL, smb_fname, &ft, true); if (!NT_STATUS_IS_OK(status)) { reply_unixerror(req, ERRDOS, ERRnoaccess); goto out; @@ -1225,7 +1225,8 @@ void reply_setatr(struct smb_request *req) reply_outbuf(req, 0, 0); - DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) ); + DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname), + mode)); out: TALLOC_FREE(smb_fname); END_PROFILE(SMBsetatr); @@ -2148,8 +2149,7 @@ void reply_mknew(struct smb_request *req) } ft.atime = smb_fname->st.st_ex_atime; /* atime. */ - status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st, - &ft, true); + status = smb_set_file_time(conn, fsp, smb_fname, &ft, true); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); goto out; @@ -2168,9 +2168,10 @@ void reply_mknew(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) ); - DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", - fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) ); + DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname))); + DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n", + smb_fname_str_dbg(smb_fname), fsp->fh->fd, + (unsigned int)fattr)); out: TALLOC_FREE(smb_fname); @@ -7582,9 +7583,9 @@ void reply_readbs(struct smb_request *req) void reply_setattrE(struct smb_request *req) { connection_struct *conn = req->conn; + struct smb_filename *smb_fname = NULL; struct smb_file_time ft; files_struct *fsp; - SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBsetattrE); @@ -7592,18 +7593,23 @@ void reply_setattrE(struct smb_request *req) if (req->wct < 7) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBsetattrE); - return; + goto out; } fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if(!fsp || (fsp->conn != conn)) { reply_doserror(req, ERRDOS, ERRbadfid); - END_PROFILE(SMBsetattrE); - return; + goto out; } + /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */ + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } /* * Convert the DOS times into unix times. @@ -7625,34 +7631,30 @@ void reply_setattrE(struct smb_request *req) /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == -1) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); - END_PROFILE(SMBsetattrE); - return; + goto out; } } else { int ret = -1; 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 == -1) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); - END_PROFILE(SMBsetattrE); - return; + goto out; } } - status = smb_set_file_time(conn, fsp, fsp->fsp_name, - &sbuf, &ft, true); + status = smb_set_file_time(conn, fsp, smb_fname, &ft, true); if (!NT_STATUS_IS_OK(status)) { reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBsetattrE); - return; + goto out; } DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u " @@ -7662,7 +7664,7 @@ void reply_setattrE(struct smb_request *req) (unsigned int)ft.mtime.tv_sec, (unsigned int)ft.create_time.tv_sec )); - + out: END_PROFILE(SMBsetattrE); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e93d313821..e5f8039e6e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4935,27 +4935,28 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, - const char *fname, - const SMB_STRUCT_STAT *psbuf, + const struct smb_filename *smb_fname, struct smb_file_time *ft, bool setting_write_time) { + struct smb_filename *smb_fname_base = NULL; uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS |FILE_NOTIFY_CHANGE_LAST_WRITE; + NTSTATUS status; - if (!VALID_STAT(*psbuf)) { + if (!VALID_STAT(smb_fname->st)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* get some defaults (no modifications) if any info is zero or -1. */ if (null_timespec(ft->atime)) { - ft->atime= psbuf->st_ex_atime; + ft->atime= smb_fname->st.st_ex_atime; action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (null_timespec(ft->mtime)) { - ft->mtime = psbuf->st_ex_mtime; + ft->mtime = smb_fname->st.st_ex_mtime; action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } @@ -4979,8 +4980,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, */ { - struct timespec mts = psbuf->st_ex_mtime; - struct timespec ats = psbuf->st_ex_atime; + struct timespec mts = smb_fname->st.st_ex_mtime; + struct timespec ats = smb_fname->st.st_ex_atime; if ((timespec_compare(&ft->atime, &ats) == 0) && (timespec_compare(&ft->mtime, &mts) == 0)) { return NT_STATUS_OK; @@ -5010,21 +5011,29 @@ NTSTATUS smb_set_file_time(connection_struct *conn, } } else { set_sticky_write_time_path( - vfs_file_id_from_sbuf(conn, psbuf), ft->mtime); + vfs_file_id_from_sbuf(conn, &smb_fname->st), + ft->mtime); } } DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); - if (fsp && fsp->base_fsp) { - fname = fsp->base_fsp->fsp_name; + /* Always call ntimes on the base, even if a stream was passed in. */ + status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name, + NULL, &smb_fname->st, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + return status; } - if(file_ntimes(conn, fname, ft, psbuf)!=0) { + if(file_ntimes(conn, smb_fname_base, ft)!=0) { + TALLOC_FREE(smb_fname_base); return map_nt_error_from_unix(errno); } - notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname); + TALLOC_FREE(smb_fname_base); + notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, + smb_fname->base_name); return NT_STATUS_OK; } @@ -5033,25 +5042,26 @@ NTSTATUS smb_set_file_time(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 dosmode) + const struct smb_filename *smb_fname, + uint32 dosmode) { - if (!VALID_STAT(*psbuf)) { + struct smb_filename *smb_fname_base = NULL; + NTSTATUS status; + + if (!VALID_STAT(smb_fname->st)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (fsp) { - if (fsp->base_fsp) { - fname = fsp->base_fsp->fsp_name; - } else { - fname = fsp->fsp_name; - } + /* Always operate on the base_name, even if a stream was passed in. */ + status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name, + NULL, &smb_fname->st, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (dosmode) { - if (S_ISDIR(psbuf->st_ex_mode)) { + if (S_ISDIR(smb_fname_base->st.st_ex_mode)) { dosmode |= aDIR; } else { dosmode &= ~aDIR; @@ -5061,29 +5071,27 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode)); /* check the mode isn't different, before changing it */ - if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, - psbuf, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n", - fname, (unsigned int)dosmode )); - - if(file_set_dosmode(conn, smb_fname, dosmode, NULL, false)) { - DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n", - fname, strerror(errno))); - TALLOC_FREE(smb_fname); - return map_nt_error_from_unix(errno); + if ((dosmode != 0) && (dosmode != dos_mode(conn, + smb_fname_base->base_name, + &smb_fname_base->st))) { + DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode " + "0x%x\n", smb_fname_str_dbg(smb_fname_base), + (unsigned int)dosmode)); + + if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL, + false)) { + DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of " + "%s failed (%s)\n", + smb_fname_str_dbg(smb_fname_base), + strerror(errno))); + status = map_nt_error_from_unix(errno); + goto out; } - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); } - return NT_STATUS_OK; + status = NT_STATUS_OK; + out: + TALLOC_FREE(smb_fname_base); + return status; } /**************************************************************************** @@ -5783,8 +5791,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - const SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { struct smb_file_time ft; ZERO_STRUCT(ft); @@ -5803,14 +5810,9 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, ft.mtime = interpret_long_date(pdata + 16); DEBUG(10,("smb_set_info_standard: file %s\n", - fname ? fname : fsp->fsp_name )); + smb_fname_str_dbg(smb_fname))); - return smb_set_file_time(conn, - fsp, - fname, - psbuf, - &ft, - true); + return smb_set_file_time(conn, fsp, smb_fname, &ft, true); } /**************************************************************************** @@ -5821,8 +5823,7 @@ static NTSTATUS smb_set_file_basic_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) { /* Patch to do this correctly from Paul Eggert . */ struct timespec write_time; @@ -5840,7 +5841,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Set the attributes */ dosmode = IVAL(pdata,32); - status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode); + status = smb_set_file_dosmode(conn, smb_fname, dosmode); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5872,15 +5873,11 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, } } - DEBUG(10,("smb_set_file_basic_info: file %s\n", - fname ? fname : fsp->fsp_name )); + DEBUG(10, ("smb_set_file_basic_info: file %s\n", + smb_fname_str_dbg(smb_fname))); - return smb_set_file_time(conn, - fsp, - fname, - psbuf, - &ft, - setting_write_time); + return smb_set_file_time(conn, fsp, smb_fname, &ft, + setting_write_time); } /**************************************************************************** @@ -6353,8 +6350,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, status = smb_set_file_time(conn, fsp, - smb_fname->base_name, - &sbuf, + smb_fname, &ft, false); if (modify_mtime) { @@ -7072,8 +7068,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } @@ -7094,8 +7089,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 e6a3940f4f..33ced8fa54 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -903,6 +903,9 @@ static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct smb_file_time ft; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + if (argc != 4) { printf("Usage: utime \n"); return NT_STATUS_OK; @@ -912,11 +915,20 @@ static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, ft.atime = convert_time_t_to_timespec(atoi(argv[2])); ft.mtime = convert_time_t_to_timespec(atoi(argv[3])); - if (SMB_VFS_NTIMES(vfs->conn, argv[1], &ft) != 0) { + + status = create_synthetic_smb_fname_split(mem_ctx, argv[1], + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (SMB_VFS_NTIMES(vfs->conn, smb_fname, &ft) != 0) { printf("utime: error=%d (%s)\n", errno, strerror(errno)); + TALLOC_FREE(smb_fname); return NT_STATUS_UNSUCCESSFUL; } + TALLOC_FREE(smb_fname); printf("utime: ok\n"); return NT_STATUS_OK; } -- cgit