📄 dir.c
字号:
}#elsestatic int fuse_readlink(struct dentry *dentry, char __user *buffer, int buflen){ int ret; char *link; link = read_link(dentry); ret = vfs_readlink(dentry, buffer, buflen, link); free_link(link); return ret;}static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd){ int ret; char *link; link = read_link(dentry); ret = vfs_follow_link(nd, link); free_link(link); return ret;}#endifstatic int fuse_dir_open(struct inode *inode, struct file *file){ return fuse_open_common(inode, file, 1);}static int fuse_dir_release(struct inode *inode, struct file *file){ return fuse_release_common(inode, file, 1);}static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync){ /* nfsd can call this with no file */ return file ? fuse_fsync_common(file, de, datasync, 1) : 0;}static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg){ unsigned ivalid = iattr->ia_valid; if (ivalid & ATTR_MODE) arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; if (ivalid & ATTR_UID) arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; if (ivalid & ATTR_GID) arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; if (ivalid & ATTR_SIZE) arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { arg->valid |= FATTR_ATIME | FATTR_MTIME;#ifdef KERNEL_2_6 arg->atime = iattr->ia_atime.tv_sec; arg->mtime = iattr->ia_mtime.tv_sec;#else arg->atime = iattr->ia_atime; arg->mtime = iattr->ia_mtime;#endif }#ifdef ATTR_FILE if (ivalid & ATTR_FILE) { struct fuse_file *ff = iattr->ia_file->private_data; arg->valid |= FATTR_FH; arg->fh = ff->fh; }#endif}/* * Set attributes, and at the same time refresh them. * * Truncation is slightly complicated, because the 'truncate' request * may fail, in which case we don't want to touch the mapping. * vmtruncate() doesn't allow for this case. So do the rlimit * checking by hand and call vmtruncate() only after the file has * actually been truncated. */static int fuse_setattr(struct dentry *entry, struct iattr *attr){ struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_req *req; struct fuse_setattr_in inarg; struct fuse_attr_out outarg; int err; int is_truncate = 0; if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { err = inode_change_ok(inode, attr); if (err) return err; } if (attr->ia_valid & ATTR_SIZE) { unsigned long limit; is_truncate = 1;#ifdef KERNEL_2_6_10_PLUS limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;#else limit = current->rlim[RLIMIT_FSIZE].rlim_cur;#endif if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { send_sig(SIGXFSZ, current, 0); return -EFBIG; } } req = fuse_get_request(fc); if (!req) return -EINTR; memset(&inarg, 0, sizeof(inarg)); iattr_to_fattr(attr, &inarg); req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; req->out.numargs = 1; req->out.args[0].size = sizeof(outarg); req->out.args[0].value = &outarg; request_send(fc, req); err = req->out.h.error; fuse_put_request(fc, req); if (!err) { if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {#ifndef KERNEL_2_6_12_PLUS if (get_node_id(inode) != FUSE_ROOT_ID) make_bad_inode(inode);#else make_bad_inode(inode);#endif err = -EIO; } else { if (is_truncate) { loff_t origsize = i_size_read(inode); i_size_write(inode, outarg.attr.size); if (origsize > outarg.attr.size) vmtruncate(inode, outarg.attr.size); } fuse_change_attributes(inode, &outarg.attr); fi->i_time = time_to_jiffies(outarg.attr_valid, outarg.attr_valid_nsec); } } else if (err == -EINTR) fuse_invalidate_attr(inode); return err;}#ifdef KERNEL_2_6static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, struct kstat *stat){ struct inode *inode = entry->d_inode; int err = fuse_revalidate(entry); if (!err) generic_fillattr(inode, stat); return err;}#else /* KERNEL_2_6 */static struct dentry *fuse_lookup_2_4(struct inode *dir, struct dentry *entry){ return fuse_lookup(dir, entry, NULL);}static int fuse_mknod_2_4(struct inode *dir, struct dentry *entry, int mode, int rdev){ return fuse_mknod(dir, entry, mode, rdev);}static int fuse_create_2_4(struct inode *dir, struct dentry *entry, int mode){ return fuse_create(dir, entry, mode, NULL);}static int fuse_permission_2_4(struct inode *inode, int mask){ return fuse_permission(inode, mask, NULL);}#endif /* KERNEL_2_6 */#ifdef HAVE_KERNEL_XATTR#ifdef KERNEL_2_6static int fuse_setxattr(struct dentry *entry, const char *name, const void *value, size_t size, int flags)#elsestatic int fuse_setxattr(struct dentry *entry, const char *name, void *value, size_t size, int flags)#endif{ struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; struct fuse_setxattr_in inarg; int err; if (fc->no_setxattr) return -EOPNOTSUPP; req = fuse_get_request(fc); if (!req) return -EINTR; memset(&inarg, 0, sizeof(inarg)); inarg.size = size; inarg.flags = flags; req->in.h.opcode = FUSE_SETXATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->in.numargs = 3; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; req->in.args[1].size = strlen(name) + 1; req->in.args[1].value = name; req->in.args[2].size = size; req->in.args[2].value = value; request_send(fc, req); err = req->out.h.error; fuse_put_request(fc, req); if (err == -ENOSYS) { fc->no_setxattr = 1; err = -EOPNOTSUPP; } return err;}static ssize_t fuse_getxattr(struct dentry *entry, const char *name, void *value, size_t size){ struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; struct fuse_getxattr_in inarg; struct fuse_getxattr_out outarg; ssize_t ret; if (fc->no_getxattr) return -EOPNOTSUPP; req = fuse_get_request(fc); if (!req) return -EINTR; memset(&inarg, 0, sizeof(inarg)); inarg.size = size; req->in.h.opcode = FUSE_GETXATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; req->in.args[1].size = strlen(name) + 1; req->in.args[1].value = name; /* This is really two different operations rolled into one */ req->out.numargs = 1; if (size) { req->out.argvar = 1; req->out.args[0].size = size; req->out.args[0].value = value; } else { req->out.args[0].size = sizeof(outarg); req->out.args[0].value = &outarg; } request_send(fc, req); ret = req->out.h.error; if (!ret) ret = size ? req->out.args[0].size : outarg.size; else { if (ret == -ENOSYS) { fc->no_getxattr = 1; ret = -EOPNOTSUPP; } } fuse_put_request(fc, req); return ret;}static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size){ struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; struct fuse_getxattr_in inarg; struct fuse_getxattr_out outarg; ssize_t ret; if (fc->no_listxattr) return -EOPNOTSUPP; req = fuse_get_request(fc); if (!req) return -EINTR; memset(&inarg, 0, sizeof(inarg)); inarg.size = size; req->in.h.opcode = FUSE_LISTXATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; /* This is really two different operations rolled into one */ req->out.numargs = 1; if (size) { req->out.argvar = 1; req->out.args[0].size = size; req->out.args[0].value = list; } else { req->out.args[0].size = sizeof(outarg); req->out.args[0].value = &outarg; } request_send(fc, req); ret = req->out.h.error; if (!ret) ret = size ? req->out.args[0].size : outarg.size; else { if (ret == -ENOSYS) { fc->no_listxattr = 1; ret = -EOPNOTSUPP; } } fuse_put_request(fc, req); return ret;}static int fuse_removexattr(struct dentry *entry, const char *name){ struct inode *inode = entry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; int err; if (fc->no_removexattr) return -EOPNOTSUPP; req = fuse_get_request(fc); if (!req) return -EINTR; req->in.h.opcode = FUSE_REMOVEXATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->in.numargs = 1; req->in.args[0].size = strlen(name) + 1; req->in.args[0].value = name; request_send(fc, req); err = req->out.h.error; fuse_put_request(fc, req); if (err == -ENOSYS) { fc->no_removexattr = 1; err = -EOPNOTSUPP; } return err;}#endifstatic struct inode_operations fuse_dir_inode_operations = {#ifdef KERNEL_2_6 .lookup = fuse_lookup,#else .lookup = fuse_lookup_2_4,#endif .mkdir = fuse_mkdir, .symlink = fuse_symlink, .unlink = fuse_unlink, .rmdir = fuse_rmdir, .rename = fuse_rename, .link = fuse_link, .setattr = fuse_setattr,#ifdef KERNEL_2_6 .create = fuse_create, .mknod = fuse_mknod, .permission = fuse_permission, .getattr = fuse_getattr,#else .create = fuse_create_2_4, .mknod = fuse_mknod_2_4, .permission = fuse_permission_2_4, .revalidate = fuse_revalidate,#endif#ifdef HAVE_KERNEL_XATTR .setxattr = fuse_setxattr, .getxattr = fuse_getxattr, .listxattr = fuse_listxattr, .removexattr = fuse_removexattr,#endif};static struct file_operations fuse_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = fuse_readdir, .open = fuse_dir_open, .release = fuse_dir_release, .fsync = fuse_dir_fsync,};static struct inode_operations fuse_common_inode_operations = { .setattr = fuse_setattr,#ifdef KERNEL_2_6 .permission = fuse_permission, .getattr = fuse_getattr,#else .permission = fuse_permission_2_4, .revalidate = fuse_revalidate,#endif#ifdef HAVE_KERNEL_XATTR .setxattr = fuse_setxattr, .getxattr = fuse_getxattr, .listxattr = fuse_listxattr, .removexattr = fuse_removexattr,#endif};static struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, .follow_link = fuse_follow_link,#ifdef KERNEL_2_6_8_PLUS .put_link = fuse_put_link, .readlink = generic_readlink,#else .readlink = fuse_readlink,#endif#ifdef KERNEL_2_6 .getattr = fuse_getattr,#else .revalidate = fuse_revalidate,#endif#ifdef HAVE_KERNEL_XATTR .setxattr = fuse_setxattr, .getxattr = fuse_getxattr, .listxattr = fuse_listxattr, .removexattr = fuse_removexattr,#endif};void fuse_init_common(struct inode *inode){ inode->i_op = &fuse_common_inode_operations;}void fuse_init_dir(struct inode *inode){ inode->i_op = &fuse_dir_inode_operations; inode->i_fop = &fuse_dir_operations;}void fuse_init_symlink(struct inode *inode){ inode->i_op = &fuse_symlink_inode_operations;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -