/* * kmap - (Linux) kernel map implementation * * Copyright (c) 2011 Guillermo Ramos <0xwille@gmail.com> * * This file is part of kmap * * kmap is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * kmap is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kmap. If not, see . */ #include #include #include #include "kmap.h" /* * Returns the node with the value passed, or NULL in case it does not exist */ static inline struct kmap *kmap_search(struct kmap *head, int value) { struct list_head *list; struct kmap *node; list_for_each(list, &head->l) { node = list_entry(list, struct kmap, l); if (node->value == value) return node; } return NULL; } /* * Prints in klog a representation of all the nodes in the map */ void kmap_display(struct kmap *head) { struct kmap *node; struct list_head *list; printk(KERN_ALERT "Displaying..."); list_for_each(list, &head->l) { node = list_entry(list, struct kmap, l); printk(KERN_ALERT " %p: v=%d d=%s\n", node, node->value, (char*)node->data); } } /* * Creates and returns a new head node */ inline struct kmap *kmap_create(void) { struct kmap *head; head = kmalloc(sizeof(struct kmap), GFP_KERNEL); if (unlikely(!head)) return NULL; INIT_LIST_HEAD(&head->l); return head; } /* * Deletes the map and frees the memory used by its nodes */ void kmap_destroy(struct kmap *head) { struct kmap *node; struct list_head *list = head->l.next; while (list != &head->l) { node = list_entry(list, struct kmap, l); list = list->next; kfree(node); } kfree(head); } /* * Creates a new node with the given value and data, and adds it to the map head */ int kmap_insert(struct kmap *head, int value, void *data) { struct kmap *new; // Key already exists if (kmap_search(head, value)) return -EINVAL; new = kmap_create(); if (unlikely(!new)) return -ENOMEM; new->value = value; new->data = data; list_add_tail(&new->l, &head->l); return 0; } /* * Removes from the map the node with the given value. */ int kmap_delete(struct kmap *head, int value) { struct kmap *node = kmap_search(head, value); if (node) { list_del(&node->l); kfree(node); return 0; } else { return -EINVAL; } } /* * Returns the data mapped to the given value, or NULL if that value has no data * associated to it */ void *kmap_get(struct kmap *head, int value) { struct kmap *node = kmap_search(head, value); if (node) return node->data; else return NULL; } /* * Associates the given value with new data, if the value was already in the map */ void kmap_set(struct kmap *head, int value, void *data) { struct kmap *node = kmap_search(head, value); if (node) node->data = data; }