42_little-penguin/ass07/main.c
2024-08-07 12:33:08 +02:00

144 lines
2.9 KiB
C

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/rwlock_types.h>
#define STUDENT_LOGIN "cchauvet"
MODULE_LICENSE("GPL");
struct dentry *subdir;
struct dentry *id_file;
struct dentry *jiffies_file;
struct dentry *foo_file;
static ssize_t id_read(struct file *, char *, size_t, loff_t *);
static ssize_t id_write(struct file *, const char *, size_t, loff_t *);
const struct file_operations id_file_fops = {
.owner = THIS_MODULE,
.write = id_write,
.read = id_read,
};
static ssize_t foo_read(struct file *, char *, size_t, loff_t *);
static ssize_t foo_write(struct file *, const char *, size_t, loff_t *);
const struct file_operations foo_file_fops = {
.owner = THIS_MODULE,
.write = foo_write,
.read = foo_read,
};
char foo_data[PAGE_SIZE];
size_t foo_data_len = 0;
DEFINE_MUTEX(foo_data_mutex);
static int __init module_start(void)
{
subdir = debugfs_create_dir("fortytwo", NULL);
if (!subdir)
goto create_fail;
id_file = debugfs_create_file("id", 0666, subdir, NULL, &id_file_fops);
if (!id_file)
goto create_fail;
debugfs_create_size_t("jiffies", 0444, subdir, (size_t *) &jiffies);
foo_file = debugfs_create_file("foo",0644, subdir, NULL, &foo_file_fops);
if (!foo_file)
goto create_fail;
printk(KERN_INFO "Hello world !\n");
return 0;
create_fail:
debugfs_remove_recursive(subdir);
return -ENOENT;
}
static void __exit module_end(void)
{
debugfs_remove_recursive(subdir);
printk(KERN_INFO "Cleaning up module.\n");
}
static ssize_t id_read(struct file *f, char *buf, size_t len, loff_t *f_pos)
{
char data[] = STUDENT_LOGIN;
size_t data_len = strlen(data);
if(*f_pos > 0)
return 0;
if (copy_to_user(buf, data, data_len))
return -EFAULT;
*f_pos += data_len;
return data_len;
}
static ssize_t id_write(struct file *f, const char *buf, size_t len, loff_t *offset)
{
char data[10];
size_t len_red = 10 > len ? len : 10;
if (copy_from_user(data, buf, len_red))
return -EFAULT;
if (strcmp(data, STUDENT_LOGIN))
return -EINVAL;
return len_red;
}
static ssize_t foo_read(struct file *f, char __user *buf, size_t len, loff_t *offset)
{
size_t len_red;
mutex_lock(&foo_data_mutex);
if (!buf)
return -EINVAL;
if (*offset > foo_data_len)
return 0;
if (len + *offset >= foo_data_len)
len_red = foo_data_len - *offset;
else
len_red = len;
if (copy_to_user(buf, foo_data + *offset, len_red))
return -EFAULT;
mutex_unlock(&foo_data_mutex);
*offset += len_red;
return len_red;
}
static ssize_t foo_write(struct file *, const char __user *buf, size_t len, loff_t *offset)
{
if (len > PAGE_SIZE)
return -EINVAL;
mutex_lock(&foo_data_mutex);
if (copy_from_user(foo_data, buf, len))
return -EFAULT;
foo_data_len = len;
mutex_unlock(&foo_data_mutex);
*offset = len;
return len;
}
module_init(module_start);
module_exit(module_end);