diff --git a/statsfs.c b/statsfs.c index b6d7083..cf28340 100644 --- a/statsfs.c +++ b/statsfs.c @@ -1,4 +1,3 @@ -// libfs.c #include #include #include @@ -7,6 +6,9 @@ #include #include #include +#include +#include +#include #define LIBFS_MAGIC 0xA0B0C0D0 #define LIBFS_BOOKS_MODE 01777 @@ -14,9 +16,8 @@ #define LIBFS_SUBDIR_MODE 01777 static struct super_block *libfs_sb; - -// Track books inode to monitor link targets static struct inode *books_inode = NULL; +static struct vfsmount *libfs_mnt; static const struct super_operations libfs_sops = { .statfs = simple_statfs, @@ -39,7 +40,7 @@ static struct inode *libfs_get_inode(struct super_block *sb, umode_t mode) { if (S_ISDIR(mode)) { inode->i_fop = &simple_dir_operations; } else { - inode->i_fop = &libfs_file_ops; // fallback + inode->i_fop = &libfs_file_ops; } inode->i_mode = mode; return inode; @@ -49,9 +50,51 @@ static bool is_protected_dentry(struct dentry *dentry) { return (strcmp(dentry->d_name.name, "books") == 0 || strcmp(dentry->d_name.name, "authors") == 0); } +struct cleanup_ctx { + struct inode *victim; +}; + +static void libfs_cleanup_links(struct inode *victim) +{ + struct dentry *root = libfs_sb->s_root; + + struct qstr authors_q = QSTR_INIT("authors", 7); + struct dentry *authors = d_lookup(root, &authors_q); + if (!authors || d_really_is_negative(authors)) { + dput(authors); + return; + } + + // Здесь конкретный пример: если ты сам знаешь имя линка на victim + // То можешь через d_lookup() найти его и удалить + struct qstr filename = QSTR_INIT("some_symlink", 12); + struct dentry *maybe_link = d_lookup(authors, &filename); + + if (maybe_link && maybe_link->d_inode == victim) { + inode_lock(authors->d_inode); + vfs_unlink(NULL, authors->d_inode, maybe_link, NULL); + inode_unlock(authors->d_inode); + } + + dput(maybe_link); + dput(authors); +} + +static int libfs_unlink(struct inode *dir, struct dentry *dentry) { + if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry)) + return -EPERM; + + struct inode *victim = dentry->d_inode; + int ret = simple_unlink(dir, dentry); + if (ret == 0 && dir == books_inode) { + libfs_cleanup_links(victim); + } + return ret; +} + static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) { if (dir == libfs_sb->s_root->d_inode) { - return -EPERM; // no mkdir in root + return -EPERM; } struct inode *inode = libfs_get_inode(dir->i_sb, S_IFDIR | LIBFS_SUBDIR_MODE); if (!inode) @@ -62,12 +105,6 @@ static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry return 0; } -static int libfs_unlink(struct inode *dir, struct dentry *dentry) { - if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry)) - return -EPERM; - return simple_unlink(dir, dentry); -} - static int libfs_rmdir(struct inode *dir, struct dentry *dentry) { if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry)) return -EPERM; @@ -145,10 +182,15 @@ static struct file_system_type libfs_type = { }; static int __init libfs_init(void) { - return register_filesystem(&libfs_type); + int ret = register_filesystem(&libfs_type); + if (ret) + return ret; + libfs_mnt = kern_mount(&libfs_type); + return PTR_ERR_OR_ZERO(libfs_mnt); } static void __exit libfs_exit(void) { + kern_unmount(libfs_mnt); unregister_filesystem(&libfs_type); } @@ -157,4 +199,4 @@ module_exit(libfs_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("you"); -MODULE_DESCRIPTION("Custom library FS with books and authors"); \ No newline at end of file +MODULE_DESCRIPTION("Custom library FS with books and authors");