www.pudn.com > cryptfs030905.rar > main.c


/*
 * Copyright (c) 1997-2003 Erez Zadok
 * Copyright (c) 2001-2003 Stony Brook 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: main.c,v 1.36 2003/07/29 18:17:20 ezk Exp $
 */

#ifdef HAVE_CONFIG_H
# include 
#endif /* HAVE_CONFIG_H */
#ifdef FISTGEN
# include "fist_cryptfs.h"
#endif /* FISTGEN */
#include "fist.h"
#include "cryptfs.h"
#include 

/* This definition must only appear after we include  */
#ifndef MODULE_LICENSE
# define MODULE_LICENSE(bison)
#endif /* not MODULE_LICENSE */


/* sb we pass is cryptfs's super_block */
int
cryptfs_interpose(dentry_t *hidden_dentry, dentry_t *dentry, super_block_t *sb, int flag)
{
    inode_t *hidden_inode;
    int err = 0;
    inode_t *inode;

    print_entry_location();

    hidden_inode = hidden_dentry->d_inode; /* CPW: moved after print_entry_location */

    ASSERT(hidden_inode != NULL);
    ASSERT(dentry->d_inode == NULL);

    /*
     * We allocate our new inode below, by calling iget.
     * iget will call our read_inode which will initialize some
     * of the new inode's fields
     */
    /* XXX: fist file systems reserve first 10 inodes */
    inode = iget(sb, cryptfs_iunique(sb, 10));

    if (!inode) {
	err = -EACCES;		/* should be impossible??? */
	goto out;
    }

    /*
     * interpose the inode if not already interposed
     *   this is possible if the inode is being reused
     * XXX: what happens if we get_empty_inode() but there's another already?
     * for now, ASSERT() that this can't happen; fix later.
     */
    if (itohi(inode) == NULL)
	itohi(inode) = igrab(hidden_inode);

    /* Use different set of inode ops for symlinks & directories*/
    if (S_ISLNK(hidden_inode->i_mode))
	inode->i_op = &cryptfs_symlink_iops;
    else if (S_ISDIR(hidden_inode->i_mode))
	inode->i_op = &cryptfs_dir_iops;
    /* Use different set of file ops for directories */
    if (S_ISDIR(hidden_inode->i_mode))
	inode->i_fop = &cryptfs_dir_fops;

    /* properly initialize special inodes */
    if (S_ISBLK(hidden_inode->i_mode) || S_ISCHR(hidden_inode->i_mode) ||
	S_ISFIFO(hidden_inode->i_mode) || S_ISSOCK(hidden_inode->i_mode)) {
	init_special_inode(inode, hidden_inode->i_mode, hidden_inode->i_rdev);
    }


    /* only (our) lookup wants to do a d_add */
    if (flag)
	d_add(dentry, inode);
    else
	d_instantiate(dentry, inode);

    ASSERT(dtopd(dentry) != NULL);

    /* all well, copy inode attributes */
    fist_copy_attr_all(inode, hidden_inode);

 out:
    print_exit_status(err);
    return err;
}


/* find hidden dentry given this cryptfs dentry */
dentry_t *
__cryptfs_hidden_dentry(char *file, char *func, int line, dentry_t *dentry)
{
    dentry_t *hidden_dentry;

    ASSERT2(dentry != NULL);
    ASSERT2(dentry->d_op != NULL);
    ASSERT2(dentry->d_op == &cryptfs_dops
	    // XXX: we may need a special version of this fxn for attach mode
	    || dentry->d_op == &cryptfs_attach_dops
	    );
    ASSERT2(dentry->d_sb->s_op == &cryptfs_sops);
    if (dentry->d_inode)
	ASSERT2(dentry->d_inode->i_op == &cryptfs_main_iops ||
		dentry->d_inode->i_op == &cryptfs_dir_iops ||
		// XXX: we may need a special version of this fxn for attach mode
		dentry->d_inode->i_op == &cryptfs_dir_attach_iops ||
		dentry->d_inode->i_op == &cryptfs_symlink_iops);

    hidden_dentry = dtohd(dentry);
    ASSERT2(hidden_dentry != NULL);
    return hidden_dentry;
}


/*
 * Parse mount options: dir=XXX and debug=N
 *
 * Returns the dentry object of the lower-level (hidden) directory;
 * We want to mount our stackable file system on top of that hidden directory.
 *
 * Sets default debugging level to N, if any.
 */
dentry_t *
cryptfs_parse_options(super_block_t *sb, char *options)
{
    dentry_t *hidden_root = ERR_PTR(-EINVAL);
    struct nameidata nd;
    char *name, *tmp, *end;
    int err = 0;

    print_entry_location();

    /* We don't want to go off the end of our arguments later on. */
    for (end = options; *end; end++);

    while (options < end) {
	tmp = options;
	while (*tmp && *tmp != ',')
	    tmp++;
	*tmp = '\0';
	if (!strncmp("dir=", options, 4)) {
	    /* note: the name passed need not be encoded */
	    name = options + 4;
	    fist_dprint(4, "cryptfs: using directory: %s\n", name);
	    if (path_init(name, LOOKUP_FOLLOW, &nd))
		err = path_walk(name, &nd);
	    if (err) {
		printk("cryptfs: error accessing hidden directory '%s'\n", name);
		hidden_root = ERR_PTR(err);
		goto out;
	    }
	    hidden_root = nd.dentry;
	    stopd(sb)->hidden_mnt = nd.mnt;
	    fist_dprint(6, "parse_options: new s_root, inode: 0x%lx, 0x%lx\n",
			(long) hidden_root, (long) hidden_root->d_inode);
	} else if (!strncmp("debug=", options, 6)) {
	    int debug = simple_strtoul(options + 6, NULL, 0);
	    fist_set_debug_value(debug);
	} else {
	    printk(KERN_WARNING "cryptfs: unrecognized option '%s'\n", options);
	}
	options = tmp + 1;
    }

out:
    print_exit_location();
    return hidden_root;
}




/* wrapper to iunique to warn if we have a wrap-around */
ino_t
cryptfs_iunique(struct super_block *sb, ino_t maxreserved)
{
    static ino_t counter = 0;
    ino_t ret;

    ret = iunique(sb, maxreserved);
    if (ret < counter) {
        printk(KERN_WARNING "%s iunique may have wrapped around!\n", __FUNCTION__);
    }
    counter = ret;

    return ret;
}


/*----*/
// this structure *must* be static!!! (or the memory for 'name' gets
// corrupted in 2.3...)
static DECLARE_FSTYPE(cryptfs_fs_type, "cryptfs", cryptfs_read_super, 0);

static int __init init_cryptfs_fs(void)
{
    printk("Registering cryptfs version $Id: main.c,v 1.36 2003/07/29 18:17:20 ezk Exp $\n");
    return register_filesystem(&cryptfs_fs_type);
}
static void __exit exit_cryptfs_fs(void)
{
    printk("Unregistering cryptfs version $Id: main.c,v 1.36 2003/07/29 18:17:20 ezk Exp $\n");
    unregister_filesystem(&cryptfs_fs_type);
}

EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Erez Zadok ");
MODULE_DESCRIPTION("FiST-generated cryptfs filesystem");
MODULE_LICENSE("LGPL");

MODULE_PARM(fist_debug_var, "i");
MODULE_PARM_DESC(fist_debug_var, "Debug level");

module_init(init_cryptfs_fs)
module_exit(exit_cryptfs_fs)

/*
 * Local variables:
 * c-basic-offset: 4
 * End:
 */