Advertisement
xosski

Character device scanner

Jan 9th, 2025
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.74 KB | None | 0 0
  1. https://github.com/BoiseState/CS453-resources/tree/master
  2.  
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/init.h>
  6. #include <linux/slab.h>
  7. #include <linux/fs.h>
  8. #include <linux/uaccess.h>
  9. #include <linux/cdev.h>
  10.  
  11. MODULE_LICENSE("GPL");
  12. MODULE_DESCRIPTION("BSU CS452 HW5");
  13. MODULE_AUTHOR("<axelmurillo@u.boisestate.edu>");
  14.  
  15. typedef struct {
  16. dev_t devno;
  17. struct cdev cdev;
  18. char *seperatorList;
  19. } Device;
  20.  
  21. typedef struct {
  22. char *s;
  23. char *separatorList;
  24. size_t inputSize;
  25. int ioctl;
  26. size_t separatorListLength;
  27. size_t inputProcessedChars;
  28. } Scanner;
  29.  
  30. static Device device;
  31.  
  32. static int open(struct inode *inode, struct file *filep) {
  33. Scanner *scanner = (Scanner *)kmalloc(sizeof(*scanner), GFP_KERNEL);
  34. if (!scanner) {
  35. printk(KERN_ERR "%s: kmalloc() failed\n",DEVNAME);
  36. return -ENOMEM;
  37. }
  38.  
  39. scanner->seperatorList = kmalloc(strlen(device.separatorList) + 1, DEVNAME);
  40. if (!scanner->separatorList) {
  41. printk(KERN_ERR "%s: kmalloc() failed for seperatorList\n",DEVNAME);
  42. kfree(scanner);
  43. return -ENOMEM;
  44. }
  45.  
  46. strcpy(scanner->seperatorList, device.separatorList);
  47. scanner->separatorListLength = strlen(device.separatorList);
  48. scanner->ioctl = 1;
  49. filp->private_data=scanner;
  50. return 0;
  51.  
  52. }
  53.  
  54. static int release(struct inode *inode, struct file *filp) {
  55. Scanner *scanner = filp->private_data;
  56. kfree(scanner->seperatorList);
  57. kfree(scanner);
  58. return 0;
  59. }
  60.  
  61. static int isCharSeparator(Scanner *scan, char cmp) {
  62. int i;
  63. for (i = 0; i < scan->separatorListLength; i++) {
  64. if (scan->separatorList[i] == cmp) {
  65. return 1;
  66. }
  67. }
  68. return 0;
  69. }
  70.  
  71. extern ssize_t read(struct file *filp, char *buf, size_t charRequested, loff_t *f_pos) {
  72. Scanner *scan = filp->private_data;
  73.  
  74. size_t numCProcessed = 0;
  75. int isSeparator = 0;
  76.  
  77. char *currToken = kmalloc(sizeof(char) * (charRequested + 1), GFP_KERNEL);
  78.  
  79. memset(currToken, 0, sizeof(char) * (charRequested + 1));
  80. if (!currToken) {
  81. printk(KERN_ERR "%s: kmalloc failed", DEVNAME);
  82. return -ENOMEM;
  83. }
  84.  
  85. while (numCProcessed < charRequested && !isSeparator && scan->inputProcessedChars < scan->inputSize) {
  86. char currChar = scan->s[scan->inputProcessedChars];
  87. isSeparator = isCharSeparator(scan, currChar);
  88.  
  89. if (!isSeparator) {
  90. currToken[numCProcessed] = currChar;
  91. currToken[numCProcessed + 1] = '\0';
  92.  
  93. numCProcessed++;
  94.  
  95. scan->inputProcessedChars++;
  96. }
  97. }
  98.  
  99. if (copy_to_user(buf, currToken, numCProcessed))
  100. {
  101. printk(KERN_ERR "%s: copy_to_user() failed\n", DEVNAME);
  102. return 0;
  103. }
  104.  
  105. kfree(currToken); //free memory allocated for currToken
  106.  
  107. if (scan->inputProcessedChars == scan->inputSize && numCProcessed == 0)
  108. {
  109. numCProcessed = -1;
  110. kfree(scan->s);
  111. }
  112. if (isSeparator && numCharsProcessed == 0)
  113. {
  114. scan->inputProcessedChars++;
  115. }
  116.  
  117. return numCProcessed;
  118. }
  119.  
  120. static long ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
  121. Scanner *scan = filp->private_data;
  122. if (cmd == 0 && arg == 0) {
  123. scan->ioctl = 0;
  124. }
  125.  
  126. return 0;
  127. }
  128.  
  129. extern ssize_t write(struct file *filp, const char *line, size_t len, loff_t *f_pos) {
  130. Scanner *scan = filp->private_data;
  131.  
  132. if (!scan->ioctl) {
  133. //free any existing lists
  134. kfree(scan->separatorList);
  135.  
  136. //allocate memory
  137. scan->separatorList = kmalloc(sizeof(char) * (len + 1), GFP_KERNEL);
  138. scan->separatorList = memset(scan->separatorList, 0, sizeof(char) * (len + 1));
  139.  
  140. //copy user data to kernel space
  141. if (copy_from_user(scan->separatorList, line, len) != 0) {
  142. printk(KERN_ERR "%s: write separators failed", DEVNAME);
  143. len = -1;
  144. }
  145.  
  146. scan->separatorListLength = len;
  147. scan->ioctl = 1;
  148. } else {
  149. //allocate memory
  150. scan->s = kmalloc(sizeof(char) * (len + 1), GFP_KERNEL);
  151. scan->s = memset(scan->s, 0, sizeof(char) * (len + 1)); //INPUT BUFFER INSTEAD!
  152.  
  153. //copy user data to kernel space
  154. if (copy_from_user(scan->s, line, len) != 0) {
  155. printk(KERN_ERR "%s: write failed", DEVNAME);
  156. len = -1;
  157. }
  158.  
  159. scan->inputSize = len;
  160. scan->inputProcessedChars = 0;
  161. }
  162. return len;
  163. }
  164.  
  165. static struct file_operations ops = {
  166. .open = open,
  167. .release = release,
  168. .read = read,
  169. .write = write,
  170. .unlocked_ioctl = ioctl,
  171. .owner = THIS_MODULE
  172. };
  173.  
  174. static int __init my_init(void) {
  175. const char *defaultSep = " \t\n:;,+-=!@./#$%&*";
  176. int err;
  177.  
  178. device.separatorList = (char *)kmalloc(strlen(defaultSep) + 1, GFP_KERNEL);
  179. if (!device.separatorList) {
  180. printk(KERN_ERR "%s: kmalloc failed\n", DEVNAME);
  181. return -ENOMEM;
  182. }
  183.  
  184. strcpy(device.separatorList, defaultSep);
  185.  
  186. err = alloc_chrdev_region(&device.devno, 0, 1, DEVNAME);
  187. if (err < 0)
  188. {
  189. printk(KERN_ERR "%s: alloc_chrdev_region() failed\n", DEVNAME);
  190. return err;
  191. }
  192.  
  193. cdev_init(&device.cdev, &ops);
  194. device.cdev.owner = THIS_MODULE;
  195.  
  196. err = cdev_add(&device.cdev, device.devno, 1);
  197. if (err)
  198. {
  199. printk(KERN_ERR "%s: cdev_add() failed\n", DEVNAME);
  200. return err;
  201. }
  202.  
  203. printk(KERN_INFO "%s: init\n", DEVNAME);
  204.  
  205. return 0;
  206. }
  207.  
  208. static void __exit my_exit(void) {
  209. cdev_del(&device.cdev);
  210.  
  211. unregister_chrdev_region(device.devno, 1);
  212.  
  213. kfree(device.seperatorList);
  214.  
  215. printk(KERN_INFO "%s: exit\n", DEVNAME);
  216. }
  217.  
  218.  
  219. module_init(my_init);
  220. module_exit(my_exit);
  221.  
  222.  
  223.  
  224.  
  225. Dr. Buffenbarger
  226. Axel Murillo
  227. CS452 Operating Systems F24
  228. 19 November 2024
  229.  
  230. ## Overview
  231.  
  232. ## How to compile and run
  233.  
  234. ### Prerequisites
  235.  
  236. ### Compilation
  237.  
  238. obj-m += my_module.o
  239.  
  240. all:
  241. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  242.  
  243. clean:
  244. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  245.  
  246. make
  247.  
  248. sudo insmod scanner_device.ko
  249.  
  250. dmesg
  251.  
  252. sudo rmmod scanner_device
  253.  
  254. ///////
  255. sudo insmod my_module.ko
  256.  
  257. ## Reflection
  258.  
  259.  
  260.  
  261. ## Valgrind
  262.  
  263. ### My valgrind output:
  264.  
  265. ==12345== Memcheck, a memory error detector
  266. ==12345== HEAP SUMMARY:
  267. ==12345== in use at exit: 0 bytes in 0 blocks
  268. ==12345== total heap usage: 3 allocs, 3 frees, 36,960 bytes allocated
  269. ==12345==
  270. ==12345== All heap blocks were freed -- no leaks are possible
  271. ==12345==
  272. ==12345== For counts of detected and suppressed errors, rerun with: -v
  273. ==12345== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
  274.  
  275.  
  276.  
  277.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement