// SPDX-License-Identifier: GPL-2.0 //#define DEBUG 1 #include #include #include #include #include #include #ifdef DEBUG #include #endif #define BUFFER_LENGTH 10 static struct dentry *folder; static struct dentry *id_file; static struct dentry *foo_file; static char *id_msg; static char *foo_msg; static struct rw_semaphore foo_sem; static ssize_t id_read(struct file *, char __user *buffer, size_t length, loff_t *offset) { int bytes = 0; const char *msg_tmp = id_msg; /* * TODO if (!*(msg_tmp + *offset)) { *offset = 0; return 0; } */ msg_tmp += *offset; while (*msg_tmp && bytes < length) { put_user(*(msg_tmp), (buffer + bytes)); bytes++; msg_tmp++; } *offset += bytes; return bytes; } static ssize_t id_write(struct file *, const char __user *buffer, size_t size, loff_t *) { int ret; char *tmp_buffer; if (size == 0) return 0; tmp_buffer = kzalloc(BUFFER_LENGTH, GFP_KERNEL); if (copy_from_user(tmp_buffer, buffer, BUFFER_LENGTH)) { kfree(tmp_buffer); return -EINVAL; } *(tmp_buffer + BUFFER_LENGTH - 1) = '\0'; pr_info("Test %s-\n", tmp_buffer); if (!strcmp(tmp_buffer, "congruent")) ret = BUFFER_LENGTH; else ret = -EINVAL; kfree(tmp_buffer); return ret; } static const struct file_operations id_fops = { .owner = THIS_MODULE, .read = id_read, .write = id_write, }; static ssize_t foo_read(struct file *, char __user *buffer, size_t count, loff_t *offset) { int bytes = -EINVAL; int tmp_len = strlen(foo_msg); if (*offset > tmp_len) { bytes = -EFAULT; } else if (down_read_trylock(&foo_sem)) { char *tmp_str = foo_msg + *offset; tmp_len = strlen(tmp_str); bytes = tmp_len > count ? count : tmp_len; if (copy_to_user(buffer, tmp_str, bytes)) bytes = -EFAULT; else *offset += bytes; #ifdef DEBUG msleep(5000); #endif up_read(&foo_sem); } return bytes; } static ssize_t foo_write(struct file *, const char __user *buffer, size_t count, loff_t *offset) { int bytes = -EINVAL; if ((*offset + count) > PAGE_SIZE) { bytes = -EFAULT; } else if (down_write_trylock(&foo_sem)) { bytes = count; if (copy_from_user(foo_msg, buffer, bytes)) bytes = -EINVAL; #ifdef DEBUG msleep(5000); #endif up_write(&foo_sem); } return bytes; } static const struct file_operations foo_fops = { .owner = THIS_MODULE, .read = foo_read, .write = foo_write, }; static int __init my_init(void) { init_rwsem(&foo_sem); id_msg = kmalloc(12, GFP_KERNEL); foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL); strscpy(id_msg, "pouetpouet\n", 12); pr_info("Coucou le gens !!!!\n"); folder = debugfs_create_dir("eudyptula", NULL); id_file = debugfs_create_file("id", 0666, folder, NULL, &id_fops); debugfs_create_u64("jiffies", 0444, folder, &jiffies_64); foo_file = debugfs_create_file("foo", 0664, folder, NULL, &foo_fops); return 0; } static void __exit my_exit(void) { debugfs_remove_recursive(folder); kfree(id_msg); kfree(foo_msg); pr_info("Tschuss !!!\n"); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("rick "); MODULE_DESCRIPTION("Module pour tester le debugfs.");