Exemple #1
0
/* Calls cr_mknod and then opens with the given flags, returning a (struct file *) */
struct file *
cr_filp_mknod(cr_errbuf_t *eb, const char *name, int mode, int flags, unsigned long unlinked_id) {
    struct nameidata nd;
    struct dentry * dentry;
    struct file *filp;

    /* mknod */
    dentry = cr_mknod(eb, &nd, name, mode, unlinked_id);
    if (IS_ERR(dentry)) {
	CR_KTRACE_UNEXPECTED("Failed to recreate %sfilesystem object %s, err=%d.",
			unlinked_id?"unlinked ":"", name, (int)PTR_ERR(dentry));
	filp = (struct file *)dentry;
	goto out;
    }

    /* now open it */
    filp = cr_dentry_open(dget(dentry), mntget(nd.nd_mnt), flags);
    if (IS_ERR(filp)) {
	CR_ERR_EB(eb, "Failed to reopen %sfilesystem object %s, err=%d.",
			unlinked_id?"unlinked ":"", name, (int)PTR_ERR(dentry));
        goto out_dput;
    }

    /* check that we actually got the expected type */
    if ((mode ^ filp->f_dentry->d_inode->i_mode) & S_IFMT) {
	CR_ERR_EB(eb, "Type conflict when recreating %sfilesystem object %s.",
			unlinked_id?"unlinked ":"", name);
	fput(filp);
	filp = ERR_PTR(-EEXIST);
	goto out_dput;
    }

out_dput:
    dput(dentry); 
    cr_path_release(&nd);
out:
    return filp;
}
Exemple #2
0
/* Calls cr_mknod and then opens with the given flags, returning a (struct file *) */
struct file *
cr_filp_mknod(cr_errbuf_t *eb, const char *name, int mode, int flags, unsigned long unlinked_id) {
    struct path path;
    struct file *filp;
    int err;

    /* mknod */
    err = cr_mknod(eb, &path, name, mode, unlinked_id);
    if (err) {
	CR_KTRACE_UNEXPECTED("Failed to recreate %sfilesystem object %s, err=%d.",
			unlinked_id?"unlinked ":"", name, err);
	filp = (struct file *)ERR_PTR(err);
	goto out;
    }

    /* now open it */
    path_get(&path);
    filp = cr_dentry_open_perm(&path, flags);
    if (IS_ERR(filp)) {
	CR_ERR_EB(eb, "Failed to reopen %sfilesystem object %s, err=%d.",
			unlinked_id?"unlinked ":"", name, (int)PTR_ERR(filp));
        goto out_put;
    }

    /* check that we actually got the expected type */
    if ((mode ^ filp->f_dentry->d_inode->i_mode) & S_IFMT) {
	CR_ERR_EB(eb, "Type conflict when recreating %sfilesystem object %s.",
			unlinked_id?"unlinked ":"", name);
	fput(filp);
	filp = ERR_PTR(-EEXIST);
    }

out_put:
    path_put(&path);
out:
    return filp;
}
Exemple #3
0
/* cr_mknod - based on linux/fs/namei.c:sys_mknod
 *
 * Creates regular files or fifos (no devices) making them anonymous (unlinked)
 * if desired.
 * Returns a dentry for the resulting filesystem objects, and the corresponding
 * vfsmnt can be obtained in nd->mnt.  Together these two can be passed
 * to dentry_open() or cr_dentry_open(), even for an unlinked inode.
 * In the event of an error, no dput() or cr_path_release() is required,
 * otherwise they are.
 *
 * In the event that an object exists with the given name, it will be
 * check for the proper mode prior to return, yielding -EEXIST on conflict.
 */
struct dentry *
cr_mknod(cr_errbuf_t *eb, struct nameidata *nd, const char *name, int mode, unsigned long unlinked_id)
{
    struct dentry * dentry;
    int err;

    if (unlinked_id) {
	/* Generate a replacement name which we will use instead of the original one. */
	name = cr_anonymous_rename(eb, name, unlinked_id);
	if (!name) {
	    CR_ERR_EB(eb, "cr_mknod - failed to rename unlinked object");
	    err = -ENOMEM;
	    goto out;
	}
    }

    /* Prior to 2.6.26, lookup_create() would return an exisiting dentry.
     * Since 2.6.26, it returns -EEXIST if the dentry exists.  So, we first
     * check for an existing dentry.  For older kernels this is not required,
     * but is still correct.
     */
    err = path_lookup(name, LOOKUP_FOLLOW, nd);
    if (!err) {
	dentry = dget(nd->nd_dentry);
	err = -EEXIST; /* Forces mode validation below */
	goto have_it;
    }

    err = path_lookup(name, LOOKUP_PARENT, nd);
    if (err) {
	CR_KTRACE_UNEXPECTED("Couldn't path_lookup for mknod %s.  err=%d.", name, err);
	goto out_free;
    }

    dentry = cr_lookup_create(nd, 0);
    if (IS_ERR(dentry)) {
	err = PTR_ERR(dentry);
	CR_KTRACE_UNEXPECTED("Couldn't lookup_create for mknod %s.  err=%d.", name, err);
	goto out_release;
    }

    switch (mode & S_IFMT) {
    case S_IFREG:
	err = vfs_create(nd->nd_dentry->d_inode, dentry, mode, nd);
	break;
    case S_IFIFO:
	err = cr_vfs_mknod(nd->nd_dentry->d_inode, dentry, nd->nd_mnt, mode, 0 /* ignored */);
	break;
    default:
	CR_ERR_EB(eb, "Unknown/invalid type %d passed to cr_mknod %s.", (mode&S_IFMT), name);
	err = -EINVAL;
    }
    if (unlinked_id && !err) { /* Note that we don't unlink if we failed to create */
	dget(dentry);	/* ensure unlink doesn't destroy the dentry */
	/* Note possibility of silent failure here: */
	(void)cr_vfs_unlink(nd->nd_dentry->d_inode, dentry, nd->nd_mnt);
	dput(dentry);
    }
    cr_inode_unlock(nd->nd_dentry->d_inode);

have_it:
    if ((err == -EEXIST) && !((dentry->d_inode->i_mode ^ mode) & S_IFMT)) {
	/* We fall through and return the dentry */
    } else if (err) {
	CR_KTRACE_UNEXPECTED("Couldn't cr_mknod %s.  err=%d.", name, err);
	goto out_put;
    }

    if (unlinked_id) {
	__putname(name);
    }
    return dentry;

out_put:
    dput(dentry);
out_release:
    cr_path_release(nd);
out_free:
    if (unlinked_id) {
	__putname(name);
    }
out:
    return (struct dentry *)ERR_PTR(err);
}