⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attach.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * Copyright (c) 1997-2000 Columbia University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. *//* *  $Id: attach.c,v 1.11 2002/12/27 20:19:03 ezk Exp $ */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* HAVE_CONFIG_H */#ifdef FISTGEN# include "fist_wrapfs.h"#endif /* FISTGEN */#include "fist.h"#include "wrapfs.h"/**************************************************************************** *** ATTACH/DETACH UTILITY AND LIST FUNCTIONS				  *** ****************************************************************************//* delete an entry if it exists *//* return true if deleted, false if not deleted */static __inline__ int del_attached_ent(super_block_t *sb, const char *name, unsigned short namelen){    attached_entry_t *ent;    struct list_head *p, *t;    write_lock(&(stopd(sb)->attachlock));    list_for_each_safe(p, t, &(stopd(sb)->attached)) {	ent = list_entry(p, attached_entry_t, list);	if (ent->e_dentry->d_name.len == namelen  &&	    strncmp(ent->e_dentry->d_name.name, name, namelen) == 0) {	    /* found entry: first unlink it from list, then dput, kfree*/	    list_del(p);	    fist_print_dentry("DAEd", ent->e_dentry);	    d_drop(ent->e_dentry);  //CPW: FIXME: d_drop correct?	    fist_print_dentry("DAEp", ent->e_dentry);	    dput(ent->e_dentry);            kfree(ent);    	    	    return 1;	}    }    write_unlock(&(stopd(sb)->attachlock));    return 0;}/* add a new entry to attached list, not checking for dups */static __inline__ void add_attached(super_block_t *sb, struct dentry *d){    attached_entry_t *ent = NULL;    ASSERT(d);    write_lock(&(stopd(sb)->attachlock));    /* allocate and fill in entry */    ent = kmalloc(sizeof(attached_entry_t), GFP_KERNEL);    ASSERT(ent);    ent->e_dentry = dget(d);    /* add to list */    list_add_tail(&(ent->list), &(stopd(sb)->attached));    write_unlock(&(stopd(sb)->attachlock));}/* * Attach (stack) a node named 'from', pointing to 'to' (hidden), * in the root of the mounted file system. */intdo_attach(inode_t *inode, file_t *file, const char *from, const char *to){    int err = -EINVAL;    dentry_t *hidden_dentry = ERR_PTR(-EINVAL);    dentry_t *this_dentry;    struct nameidata from_nd, to_nd;    super_block_t *this_sb;    print_entry_location();    printk("XXX: ATTACH %s -> %s\n", from, to);    // XXX: major issue: what inode number do we use?    // hidden inums could be duplicate...    /* get hidden (to) dentry */    if (path_init(to, LOOKUP_FOLLOW, &to_nd))	err = path_walk(to, &to_nd);    if (err) {	printk("%s: error accessing hidden directory '%s'\n", __FUNCTION__, to);	goto out;    }    // hidden_dentry->d_inode must exist    hidden_dentry = to_nd.dentry;    if (IS_ERR(hidden_dentry)) {	printk(KERN_WARNING "%s: lookup_dentry failed (err = %ld)\n",           __FUNCTION__, PTR_ERR(hidden_dentry));	err = -ENOENT;	goto out; /* CPW: FIXME: This probably needs to free resources */    }    if (!hidden_dentry->d_inode) {	printk(KERN_WARNING "%s: no directory to interpose on\n", __FUNCTION__);	err = -ENOENT;	goto out; /* CPW: FIXME: This probably needs to free resources */    }    if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) {	printk(KERN_WARNING	  "%s: can only interpose on top of directories\n", __FUNCTION__);	err = -ENOTDIR;	goto out; /* CPW: FIXME: This probably needs to free resources */    }    if (vfs_permission(hidden_dentry->d_inode, MAY_READ | MAY_EXEC)) {	printk(KERN_WARNING	  "%s: can not interpose on directories without rx permission\n", __FUNCTION__);	err = -EPERM;	goto out;    }    if (vfs_permission(hidden_dentry->d_inode, MAY_WRITE | MAY_EXEC)) {	printk(KERN_WARNING	  "%s: can not interpose without wx permission on mountpoint\n", __FUNCTION__);	err = -EPERM;	goto out;    }    this_sb = inode->i_sb;    fist_print_dentry("TOd", hidden_dentry);    /* XXX: mkdir the "from" dir??? */    /* XXX: do we need to dget() file->f_dentry (parent dir)? */    this_dentry = lookup_one_len(from, file->f_dentry, strlen(from));    if (IS_ERR(this_dentry)) {	err = PTR_ERR(this_dentry);	printk("lookup_one_len %*s in %*s failed",	       strlen(from), from,	       file->f_dentry->d_name.len, file->f_dentry->d_name.name);	goto out;    }    /* must initialize dentry operations */    this_dentry->d_op = &wrapfs_dops;    fist_print_dentry("FROMd", this_dentry);    // prepare hidden_dentry and then interpose both    ASSERT(dtopd(this_dentry) == NULL);    dtopd(this_dentry) = (struct wrapfs_dentry_info *)      kmalloc(sizeof(struct wrapfs_dentry_info), GFP_KERNEL);    if (!dtopd(this_dentry)) {	err = -ENOMEM;	goto outdput;    }    dtohd(this_dentry) = hidden_dentry;    err = wrapfs_interpose(hidden_dentry, this_dentry, this_sb, 0);    if (err)	goto outfree;    fist_print_dentry("DAd", this_dentry);    fist_print_dentry("DAp", this_dentry->d_parent);    fist_print_inode("DAi", this_dentry->d_inode);    add_attached(inode->i_sb, this_dentry);    /* increment the reference count for our superblock */    mntget(file->f_vfsmnt);    // XXX: how do we link root dentry to attached ones?    d_rehash(this_dentry);    goto outdput;  outfree:    d_drop(this_dentry);    kfree(dtopd(this_dentry));    dtopd(this_dentry) = NULL;	   outdput:    dput(this_dentry); out:    print_exit_status(err);    return err;}/* * Detach (unstack) a node named 'from' in the root of the mounted file system. */intdo_detach(inode_t *inode, file_t *file, const char *from){    attached_entry_t *ent;    struct list_head *p;    int namelen;    int err = 0;    print_entry_location();    printk("XXX: DETACH %s\n", from);    namelen = strlen(from);    if(!capable(CAP_SYS_ADMIN)) {    	read_lock(&(stopd(inode->i_sb)->attachlock));        list_for_each(p, &(stopd(inode->i_sb)->attached)) {            ent = list_entry(p, attached_entry_t, list);	    ASSERT(ent->e_dentry);	    if (ent->e_dentry->d_name.len == namelen  && 	      strncmp(ent->e_dentry->d_name.name, from, namelen) == 0) {	        if (vfs_permission(ent->e_dentry->d_inode, MAY_WRITE|MAY_EXEC)) {		    err = -EPERM;            	    read_unlock(&(stopd(inode->i_sb)->attachlock));		    goto out;	        }		break;            }        }        read_unlock(&(stopd(inode->i_sb)->attachlock));    }    if (!del_attached_ent(file->f_dentry->d_inode->i_sb, from, namelen)) {	err = -ENOENT;	goto out;    }    /* decrement the reference count for our superblock */    mntput(file->f_vfsmnt); out:    print_exit_status(err);    return err;}/**************************************************************************** *** MOUNT-TIME OPS							  *** ****************************************************************************/super_block_t *wrapfs_read_super(super_block_t *sb, void *raw_data, int silent){    super_block_t *ret_sb = NULL;    inode_t *inode;    print_entry_location();    /* XXX: not a valid test any longer, b/c we're not forcing dir=XXX       option */    if (!raw_data) {	printk(KERN_WARNING "wrapfs_read_super_attach: missing data argument\n");	goto out;    }    /* initialize private data */    stopd(sb) = kmalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL);    if (!stopd(sb)) {	printk(KERN_WARNING "%s (attach): no memory\n", __FUNCTION__);        goto out;    }    stopd(sb)->hidden_mnt = NULL;    stopd(sb)->wsi_sb = NULL;    stopd(sb)->attachlock = RW_LOCK_UNLOCKED;    INIT_LIST_HEAD(&(stopd(sb)->attached));    /* hidden_root = */ wrapfs_parse_options(sb, raw_data);    /*     * XXX: problem: we could attach multiple directories from file systems     * with differnet maxbytes.  Will it work to set it to MAX_NON_LFS or     * "infinity"?     */    sb->s_maxbytes = MAX_NON_LFS;    sb->s_op = &wrapfs_sops;    /*     * we can't use d_alloc_root if we want to use     * our own interpose function unchanged,     * so we simply replicate *most* of the code in d_alloc_root here     */    /*     * XXX: for the "attach" version of this function, we might be able to     * use d_alloc_root similarly to how proc_read_super() uses it.     */    sb->s_root = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });    if (IS_ERR(sb->s_root)) {	printk(KERN_WARNING "wrapfs_read_super_attach: d_alloc failed\n");	goto out;    }    /* XXX: do we need an "attach" version of wrapfs_dops? */    sb->s_root->d_op = &wrapfs_attach_dops;    sb->s_root->d_sb = sb;    sb->s_root->d_parent = sb->s_root;    /* link the upper and lower dentries */    dtopd(sb->s_root) = NULL;    /* XXX: copied from wrapfs_interpose (code needs to be       split/reorganized) */    inode = iget(sb, 1);	/* XXX: use get_empty_inode() later */    if (!inode) {	printk(KERN_WARNING "wrapfs_read_super_attach: iget failed\n");	goto out_dput2;    }    inode->i_op = &wrapfs_dir_attach_iops; /* XXX: need "attach" version of ops? */    inode->i_fop = &wrapfs_dir_attach_fops; /* XXX: need "attach" version of ops? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -