⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manager.c

📁 一个Windows下的Linux专用虚拟机
💻 C
字号:
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2003 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. * */#include "linux_inc.h"#include "manager.h"#include "../../ioctl.h"staticint co_os_manager_open(struct inode *inode, struct file *file){	co_manager_open_desc_t opened;	co_rc_t rc;	file->private_data = (void *)NULL;        if (!try_module_get(THIS_MODULE))		return -EBUSY;	rc = co_manager_open(co_global_manager, &opened);	if (!CO_OK(rc))		return -ENOMEM;		file->private_data = opened;	return 0;}staticint co_os_manager_ioctl_buffer(co_linux_io_t *ioctl, char *buffer, struct file *file){	co_rc_t rc;	unsigned long return_size = 0;	co_manager_open_desc_t opened = (typeof(opened))(file->private_data);	if (copy_from_user(buffer, ioctl->input_buffer, ioctl->input_buffer_size))		return -EFAULT;	rc = co_manager_ioctl(co_global_manager, 			      ioctl->code, 			      buffer, ioctl->input_buffer_size,			      ioctl->output_buffer_size, &return_size,			      opened);	if (!CO_OK(rc))		return -EIO;	if (return_size) {		if (copy_to_user(ioctl->output_buffer, buffer, return_size))			return -EFAULT;	}	if (ioctl->output_returned != NULL) {		if (copy_to_user(ioctl->output_returned, &return_size, sizeof(unsigned long))) {			return -EFAULT;		}	}	return 0;}staticint co_os_manager_ioctl(struct inode *inode, struct file *file, 			unsigned int cmd, unsigned long arg){	co_linux_io_t ioctl;	unsigned long buffer_size;	int ret = -1;	if (cmd != CO_LINUX_IOCTL_ID)		return -1;	if (copy_from_user(&ioctl, (void *)arg, sizeof(ioctl)))                return -EFAULT;	buffer_size = ioctl.input_buffer_size;	if (buffer_size < ioctl.output_buffer_size)		buffer_size = ioctl.output_buffer_size;	if (buffer_size > 0x400000)		return -EIO;		if (buffer_size > 80) {		void *buffer = vmalloc(buffer_size);		if (buffer == NULL) {			    co_debug("ioctl buffer too big: %lx", buffer_size);			    return -ENOMEM;		}		ret = co_os_manager_ioctl_buffer(&ioctl, buffer, file);		vfree(buffer);	} else {		char on_stack[80];		ret = co_os_manager_ioctl_buffer(&ioctl, on_stack, file);	}	    	return ret;}staticssize_t co_os_manager_read(struct file *file, char __user *buffer, size_t size, loff_t *poffset){	char __user *io_buffer_start;	char __user *io_buffer;	char __user *io_buffer_end;	co_manager_open_desc_t opened = (typeof(opened))(file->private_data);	int copied = 0;	int ret = -EFAULT;	co_queue_t *queue;	co_rc_t rc;	if (!opened)		return -EIO;	if (!opened->active)		return -EIO;	co_os_mutex_acquire(opened->lock);	queue = &opened->out_queue;	io_buffer_start = buffer;	io_buffer = io_buffer_start;	io_buffer_end = io_buffer + size;	while (co_queue_size(queue) != 0)	{		co_message_queue_item_t *message_item;		co_message_t *message;		unsigned long size;		rc = co_queue_peek_tail(queue, (void **)&message_item);		if (!CO_OK(rc)) {			ret = -EIO;			break;		}		message = message_item->message;		size = message->size + sizeof(*message);		if (io_buffer + size > io_buffer_end) {			break;		}				rc = co_queue_pop_tail(queue, (void **)&message_item);		if (!CO_OK(rc))			break;		co_queue_free(queue, message_item);		ret = copy_to_user(io_buffer, message, size);		if (ret) {			ret = -EFAULT;			co_os_free(message);			break;		} else {			ret = 0 ;		}		copied += size;		io_buffer += size;		co_os_free(message);	}	co_os_mutex_release(opened->lock);	*poffset += copied;	if (!ret)		return copied;	return ret;}staticssize_t co_os_manager_write(struct file *file, const char __user *buffer, size_t size, loff_t *poffset){	co_manager_open_desc_t opened = (typeof(opened))(file->private_data);	const char __user *scan_buffer;	co_message_t __user *message;	unsigned long message_size;	long size_left;	long position;	int ret = 0;	if (!opened)		return -EIO;	if (!opened->active)		return -EIO;	if (!opened->monitor)		return -EIO;	scan_buffer = buffer;	size_left = size;	position = 0;		while (size_left > 0) {		message = (typeof(message))(&scan_buffer[position]);		message_size = 0;		ret = copy_from_user(&message_size, &message->size, sizeof(message->size));		if (ret) {			ret = -EFAULT;			break;		} else {			ret = 0;		}		message_size += sizeof(*message);		size_left -= message_size;		if (size_left >= 0) {			char *kblock = kmalloc(message_size, GFP_KERNEL);			if (kblock) {				if (!copy_from_user(kblock, message, message_size)) {					co_monitor_message_from_user(opened->monitor, opened, (co_message_t *)kblock);				}				kfree(kblock);			}		}		position += message_size;	}			if (!ret)		return position;	return ret;}staticunsigned int co_os_manager_poll(struct file *file, struct poll_table_struct *pollts){	co_manager_open_desc_t opened = (typeof(opened))(file->private_data);        unsigned int mask = POLLOUT | POLLWRNORM, size;	co_queue_t *queue;	co_os_mutex_acquire(opened->lock);	queue = &opened->out_queue;	size = co_queue_size(queue);	co_os_mutex_release(opened->lock);        poll_wait(file, &opened->os->waitq, pollts);        if (size)                mask |= POLLIN | POLLRDNORM;	if (!opened->active)		mask |= POLLHUP;        return mask;	}staticint co_os_manager_release(struct inode *inode, struct file *file){	co_manager_open_desc_t opened = (typeof(opened))(file->private_data);	if (opened) {		co_manager_open_desc_deactive_and_close(co_global_manager, opened);		file->private_data = NULL;	}	module_put(THIS_MODULE);	return 0;}static struct file_operations manager_fileops = {        .open           = co_os_manager_open,	.ioctl          = co_os_manager_ioctl,	.read           = co_os_manager_read,	.write          = co_os_manager_write,	.poll           = co_os_manager_poll,        .release        = co_os_manager_release,};co_rc_t co_os_manager_init(co_manager_t *manager, co_osdep_manager_t *osdep){	co_rc_t rc = CO_RC(OK);	co_osdep_manager_t dep;	*osdep = dep = co_os_malloc(sizeof(*dep));	if (dep == NULL)		return CO_RC(OUT_OF_MEMORY);	memset(dep, 0, sizeof(*dep));	dep->proc_root = proc_mkdir("colinux", &proc_root);	if (dep->proc_root == NULL) {		rc = CO_RC(ERROR);		goto error;	}	dep->proc_root->owner = THIS_MODULE;	dep->proc_ioctl = create_proc_entry("ioctl",  S_IFREG|S_IRUSR|S_IWUSR, dep->proc_root);	if (!dep->proc_ioctl) {		rc = CO_RC(ERROR);		goto error_root;	}	dep->proc_ioctl->proc_fops = &manager_fileops;	dep->proc_ioctl->owner = THIS_MODULE;	return rc;error_root:	remove_proc_entry("colinux", &proc_root);error:	co_os_free(dep);	return rc;}void co_os_manager_free(co_osdep_manager_t osdep){	remove_proc_entry("ioctl", osdep->proc_root);	remove_proc_entry("colinux", &proc_root);	co_os_free(osdep);}co_rc_t co_os_manager_userspace_open(co_manager_open_desc_t opened){	opened->os = co_os_malloc(sizeof(*opened->os));	if (!opened->os)		return CO_RC(OUT_OF_MEMORY);	memset(opened->os, 0, sizeof(*opened->os));	init_waitqueue_head(&opened->os->waitq);	return CO_RC(OK);}void co_os_manager_userspace_close(co_manager_open_desc_t opened){	wake_up_interruptible(&opened->os->waitq);}bool_t co_os_manager_userspace_try_send_direct(	co_manager_t *manager,	co_manager_open_desc_t opened,	co_message_t *message){	wake_up_interruptible(&opened->os->waitq);	return PFALSE;}co_rc_t co_os_manager_userspace_eof(co_manager_t *manager, co_manager_open_desc_t opened){	wake_up_interruptible(&opened->os->waitq);	return CO_RC(OK);}co_id_t co_os_current_id(void){	return current->pid;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -