📄 inode.c
字号:
/* * 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: inode.c,v 1.23 2003/02/10 04:08:13 cwright 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"STATIC intwrapfs_create(inode_t *dir, dentry_t *dentry, int mode){ int err = -EACCES; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); ASSERT(hidden_dentry != NULL); fist_checkinode(dir, "wrapfs_create"); hidden_dir_dentry = lock_parent(hidden_dentry); if (IS_ERR(hidden_dir_dentry)) { err = PTR_ERR(hidden_dir_dentry); goto out; } if (!hidden_dir_dentry->d_inode->i_op || !hidden_dir_dentry->d_inode->i_op->create) goto out_lock; err = hidden_dir_dentry->d_inode->i_op->create(hidden_dir_dentry->d_inode, hidden_dentry, mode); if (err || !hidden_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); fist_checkinode(dir, "post wrapfs_create"); out_lock: unlock_dir(hidden_dir_dentry); if (!dentry->d_inode) d_drop(dentry); out: print_exit_status(err); return err;}/* * Before 2.2.7: lookup must fill in dentry and return errno (0 if ok) * Since 2.2.7: if err, returns ERR_PTR, else 0. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,7)STATIC dentry_t *#else /* kernel before 2.2.7 */STATIC int#endif /* kernel before 2.2.7 */wrapfs_lookup(inode_t *dir, dentry_t *dentry){ int err = 0; dentry_t *hidden_dir_dentry = wrapfs_hidden_dentry(dentry->d_parent); dentry_t *hidden_dentry; const char *name = dentry->d_name.name; vnode_t *this_vnode; dentry_t *this_dir;#ifdef FIST_FILTER_NAME unsigned int namelen = dentry->d_name.len; char *encoded_name; unsigned int encoded_namelen;#endif /* FIST_FILTER_NAME */ print_entry_location(); fist_checkinode(dir, "wrapfs_lookup"); this_vnode = dir; this_dir = hidden_dir_dentry; fist_print_dentry("LOOKUP: dentry IN", dentry); fist_print_dentry("LOOKUP: dentry->d_parent IN", dentry->d_parent); fist_print_dentry("LOOKUP: hidden_dir_dentry IN", hidden_dir_dentry); fist_print_inode("LOOKUP: dir IN", dir); if (hidden_dir_dentry->d_inode) fist_print_inode("LOOKUP: hidden_dir_dentry->d_inode", hidden_dir_dentry->d_inode); /* must initialize dentry operations */ dentry->d_op = &wrapfs_dops; FIST_OP_LOOKUP_PRECALL; /* increase refcount of base dentry (lookup_dentry will decrement) */ // THIS IS RIGHT! (don't "fix" it) dget(hidden_dir_dentry);#ifndef FIST_FILTER_NAME /* will allocate a new hidden dentry if needed */ hidden_dentry = lookup_dentry(name, hidden_dir_dentry, 0);#else /* FIST_FILTER_NAME */ encoded_namelen = wrapfs_encode_filename(name, namelen, &encoded_name, SKIP_DOTS, dir, dir->i_sb); /* will allocate a new hidden dentry if needed */ hidden_dentry = lookup_dentry(encoded_name, hidden_dir_dentry, 0); kfree_s(encoded_name, encoded_namelen);#endif /* FIST_FILTER_NAME */ if (IS_ERR(hidden_dentry)) { /* * this produces an unusual dentry: one that has neither an * inode, nor a private structure attached to it. All cleanup * methods (d_delete, d_release, etc) must be prepared to deal * with such dentries. Ion 09/29/2001 */ printk("ERR from hidden_dentry!!!\n"); err = PTR_ERR(hidden_dentry); goto out; } FIST_OP_LOOKUP_POSTCALL; /* update parent directory's atime */ fist_copy_attr_atime(dir, hidden_dir_dentry->d_inode); /* link the upper and lower dentries */ /* XXX allocate dentry_private_data if necessary */ dtohd(dentry) = hidden_dentry; /* lookup is special: it needs to handle negative dentries */ if (!hidden_dentry->d_inode) { d_add(dentry, NULL); fist_print_dentry("lookup hidden", hidden_dentry); goto out; } fist_dprint(6, "lookup \"%s\" -> inode %d\n", name, hidden_dentry->d_inode->i_ino); err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 1); if (err) goto out_free; fist_checkinode(dentry->d_inode, "wrapfs_lookup OUT: dentry->d_inode:"); fist_checkinode(dir, "wrapfs_lookup OUT: dir:"); fist_print_dentry(__FUNCTION__ " OUT hidden_dentry", hidden_dentry); fist_print_dentry(__FUNCTION__ " OUT hidden_dir_dentry", hidden_dir_dentry); /* All is well */ goto out; out_free: d_drop(dentry); /* XXX free dentry_private_data if necessary */ dtopd(dentry) = NULL;out: fist_print_dentry("LOOKUP: dentry OUT", dentry); print_exit_status(err);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,7) return ERR_PTR(err);#else /* kernel before 2.2.7 */ return err;#endif /* kernel before 2.2.7 */}STATIC intwrapfs_link(dentry_t *old_dentry, inode_t *dir, dentry_t *new_dentry){ int err; dentry_t *hidden_old_dentry = wrapfs_hidden_dentry(old_dentry); dentry_t *hidden_new_dentry = wrapfs_hidden_dentry(new_dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_link-dir"); fist_checkinode(old_dentry->d_inode, "wrapfs_link-oldinode"); dget(hidden_old_dentry); dget(hidden_new_dentry); hidden_dir_dentry = lock_parent(hidden_new_dentry); err = -ENOENT; if (!check_parent(hidden_dir_dentry, hidden_new_dentry)) goto out_lock; err = -EXDEV; if (hidden_dir_dentry->d_inode->i_dev != hidden_old_dentry->d_inode->i_dev) goto out_lock; err = -EPERM; if (!hidden_dir_dentry->d_inode->i_op || !hidden_dir_dentry->d_inode->i_op->link) goto out_lock; DQUOT_INIT(hidden_dir_dentry->d_inode); err = hidden_dir_dentry->d_inode->i_op->link(hidden_old_dentry, hidden_dir_dentry->d_inode, hidden_new_dentry); if (err || !hidden_new_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_new_dentry, new_dentry, dir->i_sb, 0); if (err) goto out_lock; /* * XXX: we have to do a wrapfs_copy_inode (or subset thereof) in * *ALL* functions, all file systems, and all OSs!!! */ fist_copy_attr_timesizes(dir, hidden_new_dentry->d_inode); out_lock: unlock_dir(hidden_dir_dentry); dput(hidden_new_dentry); dput(hidden_old_dentry); if (!new_dentry->d_inode) d_drop(new_dentry); print_exit_status(err); return err;}STATIC intwrapfs_unlink(inode_t *dir, dentry_t *dentry){ int err = 0; inode_t *hidden_dir = itohi(dir); dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); ASSERT(hidden_dentry != NULL); fist_checkinode(dir, "wrapfs_unlink-dir"); dget(dentry); hidden_dir_dentry = lock_parent(hidden_dentry); if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock; /* avoid destroying the hidden inode if the file is in use */ dget(hidden_dentry); err = vfs_unlink(hidden_dir, hidden_dentry); dput(hidden_dentry); if (!err) d_delete(hidden_dentry); out_lock: fist_copy_attr_times(dir, hidden_dir); /* propagate number of hard-links */ dentry->d_inode->i_nlink = itohi(dentry->d_inode)->i_nlink; unlock_dir(hidden_dir_dentry); /* * call d_drop so the system "forgets" about us */ if (!err) d_drop(dentry); dput(dentry); print_exit_status(err); return err;}STATIC intwrapfs_symlink(inode_t *dir, dentry_t *dentry, const char *symname){ int err; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; const char *hidden_symname = symname; /* XXX: can modify this */#ifdef FIST_FILTER_NAME char *encoded_symname; unsigned int encoded_symlen;#endif /* FIST_FILTER_NAME */ print_entry_location(); fist_checkinode(dir, "wrapfs_symlink-dir"); dget(hidden_dentry); hidden_dir_dentry = lock_parent(hidden_dentry); err = -ENOENT; if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock; if (!hidden_dir_dentry->d_inode->i_op || !hidden_dir_dentry->d_inode->i_op->symlink) { err = -EPERM; goto out_lock; }#ifndef FIST_FILTER_NAME err = hidden_dir_dentry->d_inode->i_op->symlink(hidden_dir_dentry->d_inode, hidden_dentry, hidden_symname);#else /* FIST_FILTER_NAME */ encoded_symlen = wrapfs_encode_filename(symname, strlen(symname), &encoded_symname, DO_DOTS, dir, dir->i_sb); err = hidden_dir_dentry->d_inode->i_op->symlink(hidden_dir_dentry->d_inode, hidden_dentry, encoded_symname); kfree_s(encoded_symname, encoded_symlen);#endif /* FIST_FILTER_NAME */ if (err || !hidden_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); fist_checkinode(dir, "post wrapfs_symlink-dir"); out_lock: unlock_dir(hidden_dir_dentry); dput(hidden_dentry); if (!dentry->d_inode) d_drop(dentry); print_exit_status(err); return err;}STATIC intwrapfs_mkdir(inode_t *dir, dentry_t *dentry, int mode){ int err; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_mkdir-dir"); hidden_dir_dentry = lock_parent(hidden_dentry); err = -ENOENT; if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock; if (!hidden_dir_dentry->d_inode->i_op || !hidden_dir_dentry->d_inode->i_op->mkdir) { err = -EPERM; goto out_lock; } err = hidden_dir_dentry->d_inode->i_op->mkdir(hidden_dir_dentry->d_inode, hidden_dentry, mode); if (err || !hidden_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); /* update number of links on parent directory */ dir->i_nlink = hidden_dir_dentry->d_inode->i_nlink; fist_checkinode(dir, "post wrapfs_mkdir-dir"); out_lock: unlock_dir(hidden_dir_dentry); if (!dentry->d_inode) d_drop(dentry); out: print_exit_status(err); return err;}STATIC intwrapfs_rmdir(inode_t *dir, dentry_t *dentry){ int err = 0; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_rmdir-dir"); dget(dentry); hidden_dir_dentry = dget(hidden_dentry->d_parent);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -