Пример #1
0
static NTSTATUS get_file_handle_for_metadata(connection_struct *conn,
				struct smb_filename *smb_fname,
				files_struct **ret_fsp,
				bool *need_close)
{
	NTSTATUS status;
	files_struct *fsp;
	struct file_id file_id;

	*need_close = false;

	if (!VALID_STAT(smb_fname->st)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);

	for(fsp = file_find_di_first(conn->sconn, file_id);
			fsp;
			fsp = file_find_di_next(fsp)) {
		if (fsp->fh->fd != -1) {
			*ret_fsp = fsp;
			return NT_STATUS_OK;
		}
	}

	/* Opens an INTERNAL_OPEN_ONLY write handle. */
	status = SMB_VFS_CREATE_FILE(
		conn,                                   /* conn */
		NULL,                                   /* req */
		0,                                      /* root_dir_fid */
		smb_fname,                              /* fname */
		FILE_WRITE_DATA,                        /* access_mask */
		(FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
			FILE_SHARE_DELETE),
		FILE_OPEN,                              /* create_disposition*/
		0,                                      /* create_options */
		0,                                      /* file_attributes */
		INTERNAL_OPEN_ONLY,                     /* oplock_request */
		NULL,					/* lease */
                0,                                      /* allocation_size */
		0,                                      /* private_flags */
		NULL,                                   /* sd */
		NULL,                                   /* ea_list */
		ret_fsp,                                /* result */
		NULL,                                   /* pinfo */
		NULL, NULL);				/* create context */

	if (NT_STATUS_IS_OK(status)) {
		*need_close = true;
	}
	return status;
}
Пример #2
0
static files_struct *irix_oplock_receive_message(fd_set *fds)
{
	extern int smb_read_error;
	oplock_stat_t os;
	char dummy;
	files_struct *fsp;

	/* Ensure we only get one call per select fd set. */
	FD_CLR(oplock_pipe_read, fds);

	/*
	 * Read one byte of zero to clear the
	 * kernel break notify message.
	 */

	if(read(oplock_pipe_read, &dummy, 1) != 1) {
		DEBUG(0,("irix_oplock_receive_message: read of kernel "
			 "notification failed. Error was %s.\n",
			 strerror(errno) ));
		smb_read_error = READ_ERROR;
		return NULL;
	}

	/*
	 * Do a query to get the
	 * device and inode of the file that has the break
	 * request outstanding.
	 */

	if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
		DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
			 "notification failed. Error was %s.\n",
			 strerror(errno) ));
		if(errno == EAGAIN) {
			/*
			 * Duplicate kernel break message - ignore.
			 */
			return NULL;
		}
		smb_read_error = READ_ERROR;
		return NULL;
	}

	/*
	 * We only have device and inode info here - we have to guess that this
	 * is the first fsp open with this dev,ino pair.
	 */

	if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev,
				      (SMB_INO_T)os.os_ino)) == NULL) {
		DEBUG(0,("irix_oplock_receive_message: unable to find open "
			 "file with dev = %x, inode = %.0f\n",
			 (unsigned int)os.os_dev, (double)os.os_ino ));
		return NULL;
	}
     
	DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
		 "received for dev = %x, inode = %.0f\n, file_id = %ul",
		 (unsigned int)fsp->dev, (double)fsp->inode,
		 fsp->fh->file_id ));

	return fsp;
}
Пример #3
0
static files_struct *irix_oplock_receive_message(struct kernel_oplocks *_ctx)
{
	struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
					   struct irix_oplocks_context);
	oplock_stat_t os;
	char dummy;
	struct file_id fileid;
	files_struct *fsp;

	/*
	 * TODO: is it correct to assume we only get one
	 * oplock break, for each byte we read from the pipe?
	 */
	ctx->pending = false;

	/*
	 * Read one byte of zero to clear the
	 * kernel break notify message.
	 */

	if(read(ctx->read_fd, &dummy, 1) != 1) {
		DEBUG(0,("irix_oplock_receive_message: read of kernel "
			 "notification failed. Error was %s.\n",
			 strerror(errno) ));
		return NULL;
	}

	/*
	 * Do a query to get the
	 * device and inode of the file that has the break
	 * request outstanding.
	 */

	if(sys_fcntl_ptr(ctx->read_fd, F_OPLKSTAT, &os) < 0) {
		DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
			 "notification failed. Error was %s.\n",
			 strerror(errno) ));
		if(errno == EAGAIN) {
			/*
			 * Duplicate kernel break message - ignore.
			 */
			return NULL;
		}
		return NULL;
	}

	/*
	 * We only have device and inode info here - we have to guess that this
	 * is the first fsp open with this dev,ino pair.
	 *
	 * NOTE: this doesn't work if any VFS modules overloads
	 *       the file_id_create() hook!
	 */

	fileid = file_id_create_dev((SMB_DEV_T)os.os_dev,
				    (SMB_INO_T)os.os_ino);
	if ((fsp = file_find_di_first(smbd_server_conn, fileid)) == NULL) {
		DEBUG(0,("irix_oplock_receive_message: unable to find open "
			 "file with dev = %x, inode = %.0f\n",
			 (unsigned int)os.os_dev, (double)os.os_ino ));
		return NULL;
	}
     
	DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
		 "received for file_id %s gen_id = %ul",
		 file_id_string_tos(&fsp->file_id),
		 fsp->fh->gen_id ));

	return fsp;
}
Пример #4
0
static int acl_common_remove_object(vfs_handle_struct *handle,
					const char *path,
					bool is_directory)
{
	connection_struct *conn = handle->conn;
	struct file_id id;
	files_struct *fsp = NULL;
	int ret = 0;
	char *parent_dir = NULL;
	const char *final_component = NULL;
	struct smb_filename local_fname;
	int saved_errno = 0;

	if (!parent_dirname(talloc_tos(), path,
			&parent_dir, &final_component)) {
		saved_errno = ENOMEM;
		goto out;
	}

	DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
		is_directory ? "directory" : "file",
		parent_dir, final_component ));

	/* cd into the parent dir to pin it. */
	ret = SMB_VFS_CHDIR(conn, parent_dir);
	if (ret == -1) {
		saved_errno = errno;
		goto out;
	}

	ZERO_STRUCT(local_fname);
	local_fname.base_name = CONST_DISCARD(char *,final_component);

	/* Must use lstat here. */
	ret = SMB_VFS_LSTAT(conn, &local_fname);
	if (ret == -1) {
		saved_errno = errno;
		goto out;
	}

	/* Ensure we have this file open with DELETE access. */
	id = vfs_file_id_from_sbuf(conn, &local_fname.st);
	for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) {
		if (fsp->access_mask & DELETE_ACCESS &&
				fsp->delete_on_close) {
			/* We did open this for delete,
			 * allow the delete as root.
			 */
			break;
		}
	}

	if (!fsp) {
		DEBUG(10,("acl_common_remove_object: %s %s/%s "
			"not an open file\n",
			is_directory ? "directory" : "file",
			parent_dir, final_component ));
		saved_errno = EACCES;
		goto out;
	}

	become_root();
	if (is_directory) {
		ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
	} else {
		ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
	}
	unbecome_root();

	if (ret == -1) {
		saved_errno = errno;
	}

  out:

	TALLOC_FREE(parent_dir);

	vfs_ChDir(conn, conn->connectpath);
	if (saved_errno) {
		errno = saved_errno;
	}
	return ret;
}