/*
* Procfs3.c-create a "file" In/proc, use the File_operation way
* To manage the file.
*/
#include <linux/kernel.h>/* We ' re doing kernel work * *
#include <linux/module.h>/* Specifically, a module * *
#include <linux/proc_fs.h>/* necessary because we use proc FS * *
#include <asm/uaccess.h>/* for Copy_*_user * *
#define PROC_ENTRY_FILENAME "BUFFER2K"
#define PROCFS_MAX_SIZE 2048
/**
* The buffer (2k) for this module
*
*/
static Char procfs_buffer[procfs_max_size];
/**
* The size of the data hold in the buffer
*
*/
static unsigned long procfs_buffer_size = 0;
/**
* The structure keeping information about The/proc file
*
*/
static struct Proc_dir_entry *our_proc_file;
/**
* This funtion was called when the/proc the file is read
*
*/
Static ssize_tProcfs_read(struct file *filp,/* include/linux/fs.h *
Char *buffer,/* buffer to fill with data * *
size_t length,/* Length of the buffer *
loff_t * Offset)
{
static int finished = 0;
/*
* We return 0 to indicate end of the file, that we have
* No more information. Otherwise, processes would
* Continue to read from the US in a endless loop.
*/
if (finished) {
PRINTK (kern_info "procfs_read:end/n");
Finished = 0;
return 0;
}
Finished = 1;
/*
* We use Put_to_user to copy of the string from the kernel ' s
* Memory segment to the memory segment of the process
* That called us. Get_from_user, BTW, is
* Used for the reverse.
*/
if (copy_to_user (buffer, Procfs_buffer, procfs_buffer_size)) {
Return-efault;
}
PRINTK (kern_info "Procfs_read:read%lu bytes/n", procfs_buffer_size);
return procfs_buffer_size; /* Return the number of bytes "read" * *
}
/*
* This function is called When/proc is written
*/
Static ssize_t
Procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
{
if (Len > Procfs_max_size) {
Procfs_buffer_size = procfs_max_size;
}
else {
Procfs_buffer_size = Len;
}
if (Copy_from_user (procfs_buffer, buffer, procfs_buffer_size)) {
Return-efault;
}
PRINTK (kern_info "Procfs_write:write%lu bytes/n", procfs_buffer_size);
return procfs_buffer_size;
}
/*
* This function decides whether to allow a operation
* (return zero) or not allow it (return a Non-zero
* Which indicates why it is not allowed).
*
* The operation can be one of the following values:
* 0-execute (Run the "file"-meaningless in my case)
* 2-write (input to the kernel module)
* 4-read (output from the kernel module)
*
* This is the real function, that checks file
* Permissions. The permissions returned by LS-L are
* For Referece only, and can is overridden here.
*/
Staticint Module_permission(struct inode *inode, int op, struct nameidata *foo)
{
/*
* We allow everybody to read from our module, but
* Only Root (uid 0) may write to it
*/
if (op = 4 | | (OP = 2 && current->euid = 0))
return 0;
/*
* If it ' s anything else, access is denied
*/
Return-eacces;
}
/*
* The file is opened-we don ' t really care about
* That, but it does mean we need to increment the
* module ' s reference count.
*/
IntProcfs_open(struct inode *inode, struct file *file)
{
Try_module_get (This_module);
return 0;
}
/*
* The file is closed-again and interesting only because
* of the reference count.
*/
IntProcfs_close(struct inode *inode, struct file *file)
{
Module_put (This_module);
return 0; * Success * *
}
static struct File_operations File_ops_4_our_proc_file = {
. Read = Procfs_read,
. write = Procfs_write,
. open = Procfs_open,
. Release = Procfs_close,
};
/*
* Inode operations for our proc file. We need it so
* we ' ll have some place to specify the file operations
* Structure we want to use, and the function we
* Permissions. It ' s also possible to specify functions
* To being called for anything else which could being done to
* An inode (although we don ' t bother, we are just put
* NULL).
*/
static struct Inode_operations Inode_ops_4_our_proc_file = {
. Permission = module_permission,/* Check for permissions * *
};
/*
* Module initialization and cleanup
*/
int Init_module ()
{
/* Create The/proc file * *
Our_proc_file = Create_proc_entry (Proc_entry_filename, 0644, NULL);
/* Check if The/proc file was created successfuly * *
if (Our_proc_file = = NULL) {
PRINTK (Kern_alert "Error:could not initialize/proc/%s/n",
Proc_entry_filename);
Return-enomem;
}
Our_proc_file->owner = This_module;
Our_proc_file->proc_iops = &Inode_ops_4_our_proc_file;
Our_proc_file->proc_fops = &File_ops_4_our_proc_file;
Our_proc_file->mode = S_ifreg | S_irugo | S_IWUSR;
Our_proc_file->uid = 0;
Our_proc_file->gid = 0;
Our_proc_file->size = 80;
PRINTK (kern_info "/proc/%s created/n", proc_entry_filename);
return 0; * Success * *
}
void Cleanup_module ()
{
Remove_proc_entry (Proc_entry_filename, &proc_root);
PRINTK (kern_info "/proc/%s removed/n", proc_entry_filename);
}