diff options
author | jdike <jdike> | 2003-09-08 16:26:19 +0000 |
---|---|---|
committer | jdike <jdike> | 2003-09-08 16:26:19 +0000 |
commit | 6149b82b1256bb2be4a3042b1c1371dc42fad931 (patch) | |
tree | 29261e5892a00f5f861a9de8da34b3f2e05db556 | |
parent | 7cc33a3d271c346196e12672e5114d911304663b (diff) | |
download | uml-history-6149b82b1256bb2be4a3042b1c1371dc42fad931.tar.gz |
Added the proc command.
A bit of code cleanup.
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 89 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_user.c | 23 | ||||
-rw-r--r-- | arch/um/include/mconsole.h | 5 |
3 files changed, 104 insertions, 13 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index f587abb..2292f5d 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -15,6 +15,8 @@ #include "linux/sysrq.h" #include "linux/tqueue.h" #include "linux/module.h" +#include "linux/file.h" +#include "linux/fs.h" #include "linux/proc_fs.h" #include "asm/irq.h" #include "asm/uaccess.h" @@ -79,7 +81,8 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) fd = (int) dev_id; while (mconsole_get_request(fd, &req)){ - if(req.cmd->as_interrupt) (*req.cmd->handler)(&req); + if(req.cmd->context == MCONSOLE_INTR) + (*req.cmd->handler)(&req); else { new = kmalloc(sizeof(req), GFP_ATOMIC); if(new == NULL) @@ -117,6 +120,90 @@ void mconsole_log(struct mc_request *req) mconsole_reply(req, "", 0, 0); } +void mconsole_proc(struct mc_request *req) +{ + struct nameidata nd; + struct file_system_type *proc; + struct super_block *super; + struct file *file; + int n, err; + char *ptr = req->request.data, *buf; + + ptr += strlen("proc"); + while(isspace(*ptr)) ptr++; + + proc = get_fs_type("proc"); + if(proc == NULL){ + mconsole_reply(req, "procfs not registered", 1, 0); + goto out; + } + + super = get_anon_super(proc, NULL, NULL); + if(super == NULL){ + mconsole_reply(req, "Failed to get procfs superblock", 1, 0); + goto out_put; + } + + if(super->s_root == NULL){ + super = (*proc->read_super)(super, NULL, 0); + if(super == NULL){ + mconsole_reply(req, "Failed to read superblock", 1, 0); + goto out_put; + } + } + up_write(&super->s_umount); + + nd.dentry = super->s_root; + nd.mnt = NULL; + nd.flags = O_RDONLY + 1; + nd.last_type = LAST_ROOT; + + err = link_path_walk(ptr, &nd); + if(err){ + mconsole_reply(req, "Failed to look up file", 1, 0); + goto out_kill; + } + + file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); + if(IS_ERR(file)){ + mconsole_reply(req, "Failed to open file", 1, 0); + goto out_kill; + } + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if(buf == NULL){ + mconsole_reply(req, "Failed to allocate buffer", 1, 0); + goto out_fput; + } + + if((file->f_op != NULL) && (file->f_op->read != NULL)){ + do { + n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, + &file->f_pos); + if(n >= 0){ + buf[n] = '\0'; + mconsole_reply(req, buf, 0, (n > 0)); + } + else { + mconsole_reply(req, "Read of file failed", + 1, 0); + goto out_free; + } + } while(n > 0); + } + else mconsole_reply(req, "", 0, 0); + + out_free: + kfree(buf); + out_fput: + fput(file); + out_kill: + kill_super(super); + out_put: + /* put_filesystem(proc); */ + out: ; +} + #define UML_MCONSOLE_HELPTEXT \ "Commands: \n\ version - Get kernel version \n\ diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index f9fcbc6..08c1074 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -18,17 +18,18 @@ #include "umid.h" static struct mconsole_command commands[] = { - { "version", mconsole_version, 1 }, - { "halt", mconsole_halt, 0 }, - { "reboot", mconsole_reboot, 0 }, - { "config", mconsole_config, 0 }, - { "remove", mconsole_remove, 0 }, - { "sysrq", mconsole_sysrq, 1 }, - { "help", mconsole_help, 1 }, - { "cad", mconsole_cad, 1 }, - { "stop", mconsole_stop, 0 }, - { "go", mconsole_go, 1 }, - { "log", mconsole_log, 1 }, + { "version", mconsole_version, MCONSOLE_INTR }, + { "halt", mconsole_halt, MCONSOLE_PROC }, + { "reboot", mconsole_reboot, MCONSOLE_PROC }, + { "config", mconsole_config, MCONSOLE_PROC }, + { "remove", mconsole_remove, MCONSOLE_PROC }, + { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, + { "help", mconsole_help, MCONSOLE_INTR }, + { "cad", mconsole_cad, MCONSOLE_INTR }, + { "stop", mconsole_stop, MCONSOLE_PROC }, + { "go", mconsole_go, MCONSOLE_INTR }, + { "log", mconsole_log, MCONSOLE_INTR }, + { "proc", mconsole_proc, MCONSOLE_PROC }, }; /* Initialized in mconsole_init, which is an initcall */ diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 14ccb3a..9fbe308 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -41,11 +41,13 @@ struct mconsole_notify { struct mc_request; +enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; + struct mconsole_command { char *command; void (*handler)(struct mc_request *req); - int as_interrupt; + enum mc_context context; }; struct mc_request @@ -78,6 +80,7 @@ extern void mconsole_cad(struct mc_request *req); extern void mconsole_stop(struct mc_request *req); extern void mconsole_go(struct mc_request *req); extern void mconsole_log(struct mc_request *req); +extern void mconsole_proc(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, |