コード例 #1
0
ファイル: smb_common_open.c プロジェクト: bahamas10/openzfs
/*
 * smb_set_open_attributes
 *
 * Last write time:
 * - If the last_write time specified in the open params is not 0 or -1,
 *   use it as file's mtime. This will be considered an explicitly set
 *   timestamps, not reset by subsequent writes.
 *
 * DOS attributes
 * - If we created_readonly, we now store the real DOS attributes
 *   (including the readonly bit) so subsequent opens will see it.
 *
 * Both are stored "pending" rather than in the file system.
 *
 * Returns: errno
 */
static int
smb_set_open_attributes(smb_request_t *sr, smb_ofile_t *of)
{
	smb_attr_t	attr;
	smb_arg_open_t	*op = &sr->sr_open;
	smb_node_t	*node = of->f_node;
	int		rc = 0;

	bzero(&attr, sizeof (smb_attr_t));

	if (op->created_readonly) {
		attr.sa_dosattr = op->dattr | FILE_ATTRIBUTE_READONLY;
		attr.sa_mask |= SMB_AT_DOSATTR;
	}

	if (op->dsize != 0) {
		attr.sa_allocsz = op->dsize;
		attr.sa_mask |= SMB_AT_ALLOCSZ;
	}

	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
		attr.sa_vattr.va_mtime = op->mtime;
		attr.sa_mask |= SMB_AT_MTIME;
	}

	/*
	 * Used to have code here to set mtime, ctime, atime
	 * when the open op->create_disposition is any of:
	 * FILE_SUPERSEDE, FILE_OVERWRITE_IF, FILE_OVERWRITE.
	 * We know that in those cases we will have set the
	 * file size, in which case the file system will
	 * update those times, so we don't have to.
	 *
	 * However, keep track of the fact that we modified
	 * the file via this handle, so we can do the evil,
	 * gratuitious mtime update on close that Windows
	 * clients appear to expect.
	 */
	if (op->action_taken == SMB_OACT_TRUNCATED)
		of->f_written = B_TRUE;

	if (attr.sa_mask != 0)
		rc = smb_node_setattr(sr, node, of->f_cr, of, &attr);

	return (rc);
}
コード例 #2
0
/*
 * smb_set_open_timestamps
 *
 * Last write time:
 * - If the last_write time specified in the open params is not 0 or -1,
 *   use it as file's mtime. This will be considered an explicitly set
 *   timestamps, not reset by subsequent writes.
 *
 * Opening existing file (not directory):
 * - If opening an existing file for overwrite set initial ATIME, MTIME
 *   & CTIME to now. (This is achieved by setting them as pending then forcing
 *   an smb_node_setattr() to apply pending times.)
 *
 * - Note  If opening an existing file NOT for overwrite, windows would
 *   set the atime on file close, however setting the atime would cause
 *   the ARCHIVE attribute to be set, which does not occur on windows,
 *   so we do not do the atime update.
 *
 * Returns: errno
 */
static int
smb_set_open_timestamps(smb_request_t *sr, smb_ofile_t *of, boolean_t created)
{
	int		rc = 0;
	smb_arg_open_t	*op = &sr->sr_open;
	smb_node_t	*node = of->f_node;
	boolean_t	existing_file, set_times;
	smb_attr_t	attr;

	bzero(&attr, sizeof (smb_attr_t));
	set_times = B_FALSE;

	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
		attr.sa_mask = SMB_AT_MTIME;
		attr.sa_vattr.va_mtime = op->mtime;
		set_times = B_TRUE;
	}

	existing_file = !(created || smb_node_is_dir(node));
	if (existing_file) {
		switch (op->create_disposition) {
		case FILE_SUPERSEDE:
		case FILE_OVERWRITE_IF:
		case FILE_OVERWRITE:
			smb_ofile_set_write_time_pending(of);
			set_times = B_TRUE;
			break;
		default:
			break;
		}
	}

	if (set_times)
		rc = smb_node_setattr(sr, node, sr->user_cr, of, &attr);

	return (rc);
}
コード例 #3
0
ファイル: smb_ofile.c プロジェクト: maosi66/illumos-joyent
/*
 * smb_ofile_close
 */
void
smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
{
	timestruc_t now;
	uint32_t flags = 0;

	SMB_OFILE_VALID(of);

	mutex_enter(&of->f_mutex);
	ASSERT(of->f_refcnt);
	switch (of->f_state) {
	case SMB_OFILE_STATE_OPEN: {

		of->f_state = SMB_OFILE_STATE_CLOSING;
		mutex_exit(&of->f_mutex);

		if (of->f_ftype == SMB_FTYPE_MESG_PIPE) {
			smb_opipe_close(of);
			smb_server_dec_pipes(of->f_server);
		} else {
			smb_attr_t *pa = &of->f_pending_attr;

			/*
			 * In here we make changes to of->f_pending_attr
			 * while not holding of->f_mutex.  This is OK
			 * because we've changed f_state to CLOSING,
			 * so no more threads will take this path.
			 */
			if (mtime_sec != 0) {
				pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
				pa->sa_mask |= SMB_AT_MTIME;
			}

			/*
			 * If we have ever modified data via this handle
			 * (write or truncate) and if the mtime was not
			 * set via this handle, update the mtime again
			 * during the close.  Windows expects this.
			 * [ MS-FSA 2.1.5.4 "Update Timestamps" ]
			 */
			if (of->f_written &&
			    (pa->sa_mask & SMB_AT_MTIME) == 0) {
				pa->sa_mask |= SMB_AT_MTIME;
				gethrestime(&now);
				pa->sa_vattr.va_mtime = now;
			}

			if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
				if (smb_tree_has_feature(of->f_tree,
				    SMB_TREE_CATIA)) {
					flags |= SMB_CATIA;
				}
				(void) smb_node_set_delete_on_close(of->f_node,
				    of->f_cr, flags);
			}
			smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
			smb_node_destroy_lock_by_ofile(of->f_node, of);

			if (smb_node_is_file(of->f_node)) {
				(void) smb_fsop_close(of->f_node, of->f_mode,
				    of->f_cr);
				smb_oplock_release(of->f_node, of);
			}
			if (smb_node_dec_open_ofiles(of->f_node) == 0) {
				/*
				 * Last close. The f_pending_attr has
				 * only times (atime,ctime,mtime) so
				 * we can borrow it to commit the
				 * n_pending_dosattr from the node.
				 */
				pa->sa_dosattr =
				    of->f_node->n_pending_dosattr;
				if (pa->sa_dosattr != 0)
					pa->sa_mask |= SMB_AT_DOSATTR;
				/* Let's leave this zero when not in use. */
				of->f_node->n_allocsz = 0;
			}
			if (pa->sa_mask != 0) {
				/*
				 * Commit any pending attributes from
				 * the ofile we're closing.  Note that
				 * we pass NULL as the ofile to setattr
				 * so it will write to the file system
				 * and not keep anything on the ofile.
				 * This clears n_pending_dosattr if
				 * there are no opens, otherwise the
				 * dosattr will be pending again.
				 */
				(void) smb_node_setattr(NULL, of->f_node,
				    of->f_cr, NULL, pa);
			}

			/*
			 * Cancel any notify change requests that
			 * may be using this open instance.
			 */
			if (of->f_node->n_fcn.fcn_count)
				smb_notify_file_closed(of);

			smb_server_dec_files(of->f_server);
		}
		atomic_dec_32(&of->f_tree->t_open_files);

		mutex_enter(&of->f_mutex);
		ASSERT(of->f_refcnt);
		ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
		of->f_state = SMB_OFILE_STATE_CLOSED;
		break;
	}
	case SMB_OFILE_STATE_CLOSED:
	case SMB_OFILE_STATE_CLOSING:
		break;

	default:
		ASSERT(0);
		break;
	}
	mutex_exit(&of->f_mutex);
}