Я пытаюсь написать простой модуль ядра, просто для целей didacti c. В частности, то, что вызывает у меня головную боль, - это поиск пути. Я хотел бы иметь запись sysfs и в операции store я хочу получить буфер и хочу сохранить его, только если это правильный путь. Поэтому я попытался использовать экспортированные символы vfs_path_lookup отсюда namei. c. Но даже вставляя правильный путь, он выводит мне сообщение ENOENT.
Это мой код:
В заголовок:
extern int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, unsigned int, struct path *path);
В функцию сохранения модуля:
ssize_t path_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count){
int err = vfs_path_lookup(current->fs->root.dentry, current->fs->root.mnt, buf, LOOKUP_DIRECTORY, base_path);
printk(KERN_DEBUG "%s\n", __FUNCTION__);
printk(KERN_DEBUG "Received: %s err is %d\n", buf, err);
strncpy(base_addr, buf, MAX_FILENAME_SIZE);
printk(KERN_DEBUG "Base Addr: %s\n", base_addr);
return strlen(base_addr);
}
Я попытался записать в файл строку "/ home / osboxes / Documents", которая является существующим каталогом. Я подозреваю, что я не получил реальное использование функции, возможно что-то с флагами. Заранее благодарю за помощь.
Редактировать: Это пример, запрошенный в комментариях (еще раз спасибо)
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#define MAX_FILENAME_SIZE 256
struct path *base_path ;
struct kobject *conf_kobj;
char base_addr[MAX_FILENAME_SIZE] = "/home/osboxes/Documenti";
struct kobj_attribute *get_attribute(char *name, umode_t mode, ssize_t (*show)(struct kobject *, struct kobj_attribute *, char *), ssize_t (*store)(struct kobject *, struct kobj_attribute *,
const char *, size_t));
ssize_t path_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf){
printk(KERN_DEBUG "%s\n", __FUNCTION__);
return sprintf(buf, "%s", base_addr);
}
ssize_t path_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count){
int err = kern_path(buf, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, base_path);
printk(KERN_DEBUG "%s\n", __FUNCTION__);
printk(KERN_DEBUG "Received: %s err is %d\n", buf, err);
strncpy(base_addr, buf, MAX_FILENAME_SIZE);
printk(KERN_DEBUG "Base Addr: %s\n", base_addr);
return strlen(base_addr);
}
static int __init init_mymodule(void)
{
struct kobj_attribute *path_attr;
printk(KERN_DEBUG "Module inserted\n");
path_attr = get_attribute(base_addr, 0666, path_show, path_store);
base_path = kmalloc(sizeof(struct path), GFP_KERNEL);
conf_kobj = kobject_create_and_add("conf", kernel_kobj);
sysfs_create_file(conf_kobj, &path_attr->attr);
return 0;
}
struct kobj_attribute *get_attribute(char *name, umode_t mode, ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf), ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count))
{
struct kobj_attribute *attribute = kmalloc(sizeof(struct kobj_attribute), GFP_KERNEL);
attribute->attr.name = name;
attribute->attr.mode = mode;
if(show)
attribute->show = show;
if(store)
attribute->store = store;
return attribute;
}
static void __exit exit_mymodule(void)
{
kobject_put(conf_kobj);
kfree(base_addr);
printk(KERN_INFO "Module removed\n");
}
module_init(init_mymodule);
module_exit(exit_mymodule);
MODULE_LICENSE("GPL");
Я также заменил vfs_path_lookup на kern_path, как предложил @Tsyvarev. Ошибка возникает, когда я пишу в терминал
echo "/home/osboxes/Documenti" > /sys/kernel/conf/path
Когда я использую адрес в переменной "buf", в этом случае он жестко закодирован, но не работает.