From: Volker Lendecke Date: Fri, 30 Dec 2022 15:26:38 +0000 (+0100) Subject: smbd: Move SMB_SET_FILE_UNIX_[BASIC|INFO2] to smb1_trans2.c X-Git-Tag: talloc-2.4.0~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2be0e68ec512b77f525edba904c25c545d2605dd;p=thirdparty%2Fsamba.git smbd: Move SMB_SET_FILE_UNIX_[BASIC|INFO2] to smb1_trans2.c Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c index 4a56e9f2407..dfa0af082cd 100644 --- a/source3/smbd/smb1_trans2.c +++ b/source3/smbd/smb1_trans2.c @@ -3200,6 +3200,417 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, smb_fname_new); } +/**************************************************************************** + Allow a UNIX info mknod. +****************************************************************************/ + +static NTSTATUS smb_unix_mknod(connection_struct *conn, + const char *pdata, + int total_data, + const struct smb_filename *smb_fname) +{ + uint32_t file_type = IVAL(pdata,56); +#if defined(HAVE_MAKEDEV) + uint32_t dev_major = IVAL(pdata,60); + uint32_t dev_minor = IVAL(pdata,68); +#endif + SMB_DEV_T dev = (SMB_DEV_T)0; + uint32_t raw_unixmode = IVAL(pdata,84); + NTSTATUS status; + mode_t unixmode; + int ret; + struct smb_filename *parent_fname = NULL; + struct smb_filename *base_name = NULL; + + if (total_data < 100) { + return NT_STATUS_INVALID_PARAMETER; + } + + status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, + PERM_NEW_FILE, &unixmode); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + +#if defined(HAVE_MAKEDEV) + dev = makedev(dev_major, dev_minor); +#endif + + switch (file_type) { + /* We can't create other objects here. */ + case UNIX_TYPE_FILE: + case UNIX_TYPE_DIR: + case UNIX_TYPE_SYMLINK: + return NT_STATUS_ACCESS_DENIED; +#if defined(S_IFIFO) + case UNIX_TYPE_FIFO: + unixmode |= S_IFIFO; + break; +#endif +#if defined(S_IFSOCK) + case UNIX_TYPE_SOCKET: + unixmode |= S_IFSOCK; + break; +#endif +#if defined(S_IFCHR) + case UNIX_TYPE_CHARDEV: + /* This is only allowed for root. */ + if (get_current_uid(conn) != sec_initial_uid()) { + return NT_STATUS_ACCESS_DENIED; + } + unixmode |= S_IFCHR; + break; +#endif +#if defined(S_IFBLK) + case UNIX_TYPE_BLKDEV: + if (get_current_uid(conn) != sec_initial_uid()) { + return NT_STATUS_ACCESS_DENIED; + } + unixmode |= S_IFBLK; + break; +#endif + default: + 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, smb_fname_str_dbg(smb_fname))); + + status = parent_pathref(talloc_tos(), + conn->cwd_fsp, + smb_fname, + &parent_fname, + &base_name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Ok - do the mknod. */ + ret = SMB_VFS_MKNODAT(conn, + parent_fname->fsp, + base_name, + unixmode, + dev); + + if (ret != 0) { + TALLOC_FREE(parent_fname); + return map_nt_error_from_unix(errno); + } + + /* If any of the other "set" calls fail we + * don't want to end up with a half-constructed mknod. + */ + + if (lp_inherit_permissions(SNUM(conn))) { + inherit_access_posix_acl(conn, + parent_fname->fsp, + smb_fname, + unixmode); + } + TALLOC_FREE(parent_fname); + + return NT_STATUS_OK; +} + +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_BASIC. +****************************************************************************/ + +static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, + struct smb_request *req, + const char *pdata, + int total_data, + files_struct *fsp, + struct smb_filename *smb_fname) +{ + struct smb_file_time ft; + uint32_t raw_unixmode; + mode_t unixmode; + off_t size = 0; + uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; + gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; + NTSTATUS status = NT_STATUS_OK; + enum perm_type ptype; + files_struct *all_fsps = NULL; + bool modify_mtime = true; + struct file_id id; + SMB_STRUCT_STAT sbuf; + + if (!CAN_WRITE(conn)) { + return NT_STATUS_DOS(ERRSRV, ERRaccess); + } + + init_smb_file_time(&ft); + + if (total_data < 100) { + return NT_STATUS_INVALID_PARAMETER; + } + + if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && + IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { + size=IVAL(pdata,0); /* first 8 Bytes are size */ + size |= (((off_t)IVAL(pdata,4)) << 32); + } + + ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */ + ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */ + set_owner = (uid_t)IVAL(pdata,40); + set_grp = (gid_t)IVAL(pdata,48); + raw_unixmode = IVAL(pdata,84); + + if (VALID_STAT(smb_fname->st)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { + ptype = PERM_EXISTING_DIR; + } else { + ptype = PERM_EXISTING_FILE; + } + } else { + ptype = PERM_NEW_FILE; + } + + 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", + smb_fname_str_dbg(smb_fname), (double)size, + (unsigned int)set_owner, (unsigned int)set_grp, + (int)raw_unixmode)); + + sbuf = smb_fname->st; + + if (!VALID_STAT(sbuf)) { + /* + * The only valid use of this is to create character and block + * devices, and named pipes. This is deprecated (IMHO) and + * a new info level should be used for mknod. JRA. + */ + + return smb_unix_mknod(conn, + pdata, + total_data, + smb_fname); + } + +#if 1 + /* Horrible backwards compatibility hack as an old server bug + * allowed a CIFS client bug to remain unnoticed :-(. JRA. + * */ + + if (!size) { + size = get_file_size_stat(&sbuf); + } +#endif + + /* + * Deal with the UNIX specific mode set. + */ + + if (raw_unixmode != SMB_MODE_NO_CHANGE) { + int ret; + + if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) { + DBG_WARNING("Can't set mode on symlink %s\n", + smb_fname_str_dbg(smb_fname)); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + 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))); + ret = SMB_VFS_FCHMOD(fsp, unixmode); + if (ret != 0) { + return map_nt_error_from_unix(errno); + } + } + + /* + * Deal with the UNIX specific uid set. + */ + + 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, + smb_fname_str_dbg(smb_fname))); + + if (fsp && + !fsp->fsp_flags.is_pathref && + fsp_get_io_fd(fsp) != -1) + { + ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1); + } else { + /* + * UNIX extensions calls must always operate + * on symlinks. + */ + ret = SMB_VFS_LCHOWN(conn, smb_fname, + set_owner, (gid_t)-1); + } + + if (ret != 0) { + status = map_nt_error_from_unix(errno); + return status; + } + } + + /* + * Deal with the UNIX specific gid set. + */ + + if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && + (sbuf.st_ex_gid != set_grp)) { + int ret; + + DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " + "changing group %u for file %s\n", + (unsigned int)set_grp, + smb_fname_str_dbg(smb_fname))); + if (fsp && + !fsp->fsp_flags.is_pathref && + fsp_get_io_fd(fsp) != -1) + { + ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp); + } else { + /* + * UNIX extensions calls must always operate + * on symlinks. + */ + ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1, + set_grp); + } + if (ret != 0) { + status = map_nt_error_from_unix(errno); + return status; + } + } + + /* Deal with any size changes. */ + + if (S_ISREG(sbuf.st_ex_mode)) { + status = smb_set_file_size(conn, req, + fsp, + smb_fname, + &sbuf, + size, + false); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + /* Deal with any time changes. */ + if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) { + /* No change, don't cancel anything. */ + return status; + } + + id = vfs_file_id_from_sbuf(conn, &sbuf); + for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps; + all_fsps = file_find_di_next(all_fsps, true)) { + /* + * We're setting the time explicitly for UNIX. + * Cancel any pending changes over all handles. + */ + all_fsps->fsp_flags.update_write_time_on_close = false; + TALLOC_FREE(all_fsps->update_write_time_event); + } + + /* + * Override the "setting_write_time" + * parameter here as it almost does what + * we need. Just remember if we modified + * mtime and send the notify ourselves. + */ + if (is_omit_timespec(&ft.mtime)) { + modify_mtime = false; + } + + status = smb_set_file_time(conn, + fsp, + smb_fname, + &ft, + false); + if (modify_mtime) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name); + } + return status; +} + +/**************************************************************************** + Deal with SMB_SET_FILE_UNIX_INFO2. +****************************************************************************/ + +static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, + struct smb_request *req, + const char *pdata, + int total_data, + files_struct *fsp, + struct smb_filename *smb_fname) +{ + NTSTATUS status; + uint32_t smb_fflags; + uint32_t smb_fmask; + + if (!CAN_WRITE(conn)) { + return NT_STATUS_DOS(ERRSRV, ERRaccess); + } + + if (total_data < 116) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* Start by setting all the fields that are common between UNIX_BASIC + * and UNIX_INFO2. + */ + status = smb_set_file_unix_basic(conn, req, pdata, total_data, + fsp, smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + smb_fflags = IVAL(pdata, 108); + smb_fmask = IVAL(pdata, 112); + + /* NB: We should only attempt to alter the file flags if the client + * sends a non-zero mask. + */ + if (smb_fmask != 0) { + int stat_fflags = 0; + + 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; + } + + if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) { + DBG_WARNING("Can't change flags on symlink %s\n", + smb_fname_str_dbg(smb_fname)); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) { + return map_nt_error_from_unix(errno); + } + } + + /* XXX: need to add support for changing the create_time here. You + * can do this for paths on Darwin with setattrlist(2). The right way + * to hook this up is probably by extending the VFS utimes interface. + */ + + return NT_STATUS_OK; +} + static void call_trans2setpathinfo( connection_struct *conn, struct smb_request *req, @@ -3328,6 +3739,26 @@ static void call_trans2setpathinfo( status = smb_set_file_unix_hlink( conn, req, *ppdata, total_data, smb_fname); break; + + case SMB_SET_FILE_UNIX_BASIC: + status = smb_set_file_unix_basic( + conn, + req, + *ppdata, + total_data, + smb_fname->fsp, + smb_fname); + break; + + case SMB_SET_FILE_UNIX_INFO2: + status = smb_set_file_unix_info2( + conn, + req, + *ppdata, + total_data, + smb_fname->fsp, + smb_fname); + break; } if (info_level_handled) { @@ -3510,6 +3941,16 @@ static void call_trans2setfileinfo( info_level_handled = false; break; + case SMB_SET_FILE_UNIX_BASIC: + status = smb_set_file_unix_basic( + conn, req, pdata, total_data, fsp, smb_fname); + break; + + case SMB_SET_FILE_UNIX_INFO2: + status = smb_set_file_unix_info2( + conn, req, pdata, total_data, fsp, smb_fname); + break; + case SMB_SET_POSIX_LOCK: status = smb_set_posix_lock( conn, req, *ppdata, total_data, fsp); diff --git a/source3/smbd/smb2_trans2.c b/source3/smbd/smb2_trans2.c index c86c1c0b774..275cd3be93c 100644 --- a/source3/smbd/smb2_trans2.c +++ b/source3/smbd/smb2_trans2.c @@ -5764,409 +5764,6 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn, fail_after_createfile); } -/**************************************************************************** - Allow a UNIX info mknod. -****************************************************************************/ - -static NTSTATUS smb_unix_mknod(connection_struct *conn, - const char *pdata, - int total_data, - const struct smb_filename *smb_fname) -{ - uint32_t file_type = IVAL(pdata,56); -#if defined(HAVE_MAKEDEV) - uint32_t dev_major = IVAL(pdata,60); - uint32_t dev_minor = IVAL(pdata,68); -#endif - SMB_DEV_T dev = (SMB_DEV_T)0; - uint32_t raw_unixmode = IVAL(pdata,84); - NTSTATUS status; - mode_t unixmode; - int ret; - struct smb_filename *parent_fname = NULL; - struct smb_filename *base_name = NULL; - - if (total_data < 100) { - return NT_STATUS_INVALID_PARAMETER; - } - - status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, - PERM_NEW_FILE, &unixmode); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - -#if defined(HAVE_MAKEDEV) - dev = makedev(dev_major, dev_minor); -#endif - - switch (file_type) { - /* We can't create other objects here. */ - case UNIX_TYPE_FILE: - case UNIX_TYPE_DIR: - case UNIX_TYPE_SYMLINK: - return NT_STATUS_ACCESS_DENIED; -#if defined(S_IFIFO) - case UNIX_TYPE_FIFO: - unixmode |= S_IFIFO; - break; -#endif -#if defined(S_IFSOCK) - case UNIX_TYPE_SOCKET: - unixmode |= S_IFSOCK; - break; -#endif -#if defined(S_IFCHR) - case UNIX_TYPE_CHARDEV: - /* This is only allowed for root. */ - if (get_current_uid(conn) != sec_initial_uid()) { - return NT_STATUS_ACCESS_DENIED; - } - unixmode |= S_IFCHR; - break; -#endif -#if defined(S_IFBLK) - case UNIX_TYPE_BLKDEV: - if (get_current_uid(conn) != sec_initial_uid()) { - return NT_STATUS_ACCESS_DENIED; - } - unixmode |= S_IFBLK; - break; -#endif - default: - 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, smb_fname_str_dbg(smb_fname))); - - status = parent_pathref(talloc_tos(), - conn->cwd_fsp, - smb_fname, - &parent_fname, - &base_name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* Ok - do the mknod. */ - ret = SMB_VFS_MKNODAT(conn, - parent_fname->fsp, - base_name, - unixmode, - dev); - - if (ret != 0) { - TALLOC_FREE(parent_fname); - return map_nt_error_from_unix(errno); - } - - /* If any of the other "set" calls fail we - * don't want to end up with a half-constructed mknod. - */ - - if (lp_inherit_permissions(SNUM(conn))) { - inherit_access_posix_acl(conn, - parent_fname->fsp, - smb_fname, - unixmode); - } - TALLOC_FREE(parent_fname); - - return NT_STATUS_OK; -} - -/**************************************************************************** - Deal with SMB_SET_FILE_UNIX_BASIC. -****************************************************************************/ - -static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, - struct smb_request *req, - const char *pdata, - int total_data, - files_struct *fsp, - struct smb_filename *smb_fname) -{ - struct smb_file_time ft; - uint32_t raw_unixmode; - mode_t unixmode; - off_t size = 0; - uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE; - gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; - NTSTATUS status = NT_STATUS_OK; - enum perm_type ptype; - files_struct *all_fsps = NULL; - bool modify_mtime = true; - struct file_id id; - SMB_STRUCT_STAT sbuf; - - init_smb_file_time(&ft); - - if (total_data < 100) { - return NT_STATUS_INVALID_PARAMETER; - } - - if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && - IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { - size=IVAL(pdata,0); /* first 8 Bytes are size */ - size |= (((off_t)IVAL(pdata,4)) << 32); - } - - ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */ - ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */ - set_owner = (uid_t)IVAL(pdata,40); - set_grp = (gid_t)IVAL(pdata,48); - raw_unixmode = IVAL(pdata,84); - - if (VALID_STAT(smb_fname->st)) { - if (S_ISDIR(smb_fname->st.st_ex_mode)) { - ptype = PERM_EXISTING_DIR; - } else { - ptype = PERM_EXISTING_FILE; - } - } else { - ptype = PERM_NEW_FILE; - } - - 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", - smb_fname_str_dbg(smb_fname), (double)size, - (unsigned int)set_owner, (unsigned int)set_grp, - (int)raw_unixmode)); - - sbuf = smb_fname->st; - - if (!VALID_STAT(sbuf)) { - /* - * The only valid use of this is to create character and block - * devices, and named pipes. This is deprecated (IMHO) and - * a new info level should be used for mknod. JRA. - */ - - return smb_unix_mknod(conn, - pdata, - total_data, - smb_fname); - } - -#if 1 - /* Horrible backwards compatibility hack as an old server bug - * allowed a CIFS client bug to remain unnoticed :-(. JRA. - * */ - - if (!size) { - size = get_file_size_stat(&sbuf); - } -#endif - - /* - * Deal with the UNIX specific mode set. - */ - - if (raw_unixmode != SMB_MODE_NO_CHANGE) { - int ret; - - if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) { - DBG_WARNING("Can't set mode on symlink %s\n", - smb_fname_str_dbg(smb_fname)); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - 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))); - ret = SMB_VFS_FCHMOD(fsp, unixmode); - if (ret != 0) { - return map_nt_error_from_unix(errno); - } - } - - /* - * Deal with the UNIX specific uid set. - */ - - 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, - smb_fname_str_dbg(smb_fname))); - - if (fsp && - !fsp->fsp_flags.is_pathref && - fsp_get_io_fd(fsp) != -1) - { - ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1); - } else { - /* - * UNIX extensions calls must always operate - * on symlinks. - */ - ret = SMB_VFS_LCHOWN(conn, smb_fname, - set_owner, (gid_t)-1); - } - - if (ret != 0) { - status = map_nt_error_from_unix(errno); - return status; - } - } - - /* - * Deal with the UNIX specific gid set. - */ - - if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && - (sbuf.st_ex_gid != set_grp)) { - int ret; - - DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC " - "changing group %u for file %s\n", - (unsigned int)set_grp, - smb_fname_str_dbg(smb_fname))); - if (fsp && - !fsp->fsp_flags.is_pathref && - fsp_get_io_fd(fsp) != -1) - { - ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp); - } else { - /* - * UNIX extensions calls must always operate - * on symlinks. - */ - ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1, - set_grp); - } - if (ret != 0) { - status = map_nt_error_from_unix(errno); - return status; - } - } - - /* Deal with any size changes. */ - - if (S_ISREG(sbuf.st_ex_mode)) { - status = smb_set_file_size(conn, req, - fsp, - smb_fname, - &sbuf, - size, - false); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - - /* Deal with any time changes. */ - if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) { - /* No change, don't cancel anything. */ - return status; - } - - id = vfs_file_id_from_sbuf(conn, &sbuf); - for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps; - all_fsps = file_find_di_next(all_fsps, true)) { - /* - * We're setting the time explicitly for UNIX. - * Cancel any pending changes over all handles. - */ - all_fsps->fsp_flags.update_write_time_on_close = false; - TALLOC_FREE(all_fsps->update_write_time_event); - } - - /* - * Override the "setting_write_time" - * parameter here as it almost does what - * we need. Just remember if we modified - * mtime and send the notify ourselves. - */ - if (is_omit_timespec(&ft.mtime)) { - modify_mtime = false; - } - - status = smb_set_file_time(conn, - fsp, - smb_fname, - &ft, - false); - if (modify_mtime) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name); - } - return status; -} - -/**************************************************************************** - Deal with SMB_SET_FILE_UNIX_INFO2. -****************************************************************************/ - -static NTSTATUS smb_set_file_unix_info2(connection_struct *conn, - struct smb_request *req, - const char *pdata, - int total_data, - files_struct *fsp, - struct smb_filename *smb_fname) -{ - NTSTATUS status; - uint32_t smb_fflags; - uint32_t smb_fmask; - - if (total_data < 116) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* Start by setting all the fields that are common between UNIX_BASIC - * and UNIX_INFO2. - */ - status = smb_set_file_unix_basic(conn, req, pdata, total_data, - fsp, smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - smb_fflags = IVAL(pdata, 108); - smb_fmask = IVAL(pdata, 112); - - /* NB: We should only attempt to alter the file flags if the client - * sends a non-zero mask. - */ - if (smb_fmask != 0) { - int stat_fflags = 0; - - 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; - } - - if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) { - DBG_WARNING("Can't change flags on symlink %s\n", - smb_fname_str_dbg(smb_fname)); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) { - return map_nt_error_from_unix(errno); - } - } - - /* XXX: need to add support for changing the create_time here. You - * can do this for paths on Darwin with setattrlist(2). The right way - * to hook this up is probably by extending the VFS utimes interface. - */ - - return NT_STATUS_OK; -} - static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn, struct smb_request *req, TALLOC_CTX *mem_ctx, @@ -6198,25 +5795,6 @@ static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn, total_data); switch (info_level) { - case SMB_SET_FILE_UNIX_BASIC: - { - status = smb_set_file_unix_basic(conn, req, - pdata, - total_data, - fsp, - smb_fname); - break; - } - - case SMB_SET_FILE_UNIX_INFO2: - { - status = smb_set_file_unix_info2(conn, req, - pdata, - total_data, - fsp, - smb_fname); - break; - } #if defined(HAVE_POSIX_ACLS) case SMB_SET_POSIX_ACL: