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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		loff_t num_extents;		num_extents = upper_size >> crypt_stat->extent_shift;		if (upper_size & ~crypt_stat->extent_mask)			num_extents++;		lower_size += (num_extents * crypt_stat->extent_size);	}	return lower_size;}/** * ecryptfs_truncate * @dentry: The ecryptfs layer dentry * @new_length: The length to expand the file to * * Function to handle truncations modifying the size of the file. Note * that the file sizes are interpolated. When expanding, we are simply * writing strings of 0's out. When truncating, we need to modify the * underlying file size according to the page index interpolations. * * Returns zero on success; non-zero otherwise */int ecryptfs_truncate(struct dentry *dentry, loff_t new_length){	int rc = 0;	struct inode *inode = dentry->d_inode;	struct dentry *lower_dentry;	struct file fake_ecryptfs_file;	struct ecryptfs_crypt_stat *crypt_stat;	loff_t i_size = i_size_read(inode);	loff_t lower_size_before_truncate;	loff_t lower_size_after_truncate;	if (unlikely((new_length == i_size)))		goto out;	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;	/* Set up a fake ecryptfs file, this is used to interface with	 * the file in the underlying filesystem so that the	 * truncation has an effect there as well. */	memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file));	fake_ecryptfs_file.f_path.dentry = dentry;	/* Released at out_free: label */	ecryptfs_set_file_private(&fake_ecryptfs_file,				  kmem_cache_alloc(ecryptfs_file_info_cache,						   GFP_KERNEL));	if (unlikely(!ecryptfs_file_to_private(&fake_ecryptfs_file))) {		rc = -ENOMEM;		goto out;	}	lower_dentry = ecryptfs_dentry_to_lower(dentry);	ecryptfs_set_file_lower(		&fake_ecryptfs_file,		ecryptfs_inode_to_private(dentry->d_inode)->lower_file);	/* Switch on growing or shrinking file */	if (new_length > i_size) {		char zero[] = { 0x00 };		/* Write a single 0 at the last position of the file;		 * this triggers code that will fill in 0's throughout		 * the intermediate portion of the previous end of the		 * file and the new and of the file */		rc = ecryptfs_write(&fake_ecryptfs_file, zero,				    (new_length - 1), 1);	} else { /* new_length < i_size_read(inode) */		/* We're chopping off all the pages down do the page		 * in which new_length is located. Fill in the end of		 * that page from (new_length & ~PAGE_CACHE_MASK) to		 * PAGE_CACHE_SIZE with zeros. */		size_t num_zeros = (PAGE_CACHE_SIZE				    - (new_length & ~PAGE_CACHE_MASK));		if (num_zeros) {			char *zeros_virt;			zeros_virt = kzalloc(num_zeros, GFP_KERNEL);			if (!zeros_virt) {				rc = -ENOMEM;				goto out_free;			}			rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt,					    new_length, num_zeros);			kfree(zeros_virt);			if (rc) {				printk(KERN_ERR "Error attempting to zero out "				       "the remainder of the end page on "				       "reducing truncate; rc = [%d]\n", rc);				goto out_free;			}		}		vmtruncate(inode, new_length);		rc = ecryptfs_write_inode_size_to_metadata(inode);		if (rc) {			printk(KERN_ERR	"Problem with "			       "ecryptfs_write_inode_size_to_metadata; "			       "rc = [%d]\n", rc);			goto out_free;		}		/* We are reducing the size of the ecryptfs file, and need to		 * know if we need to reduce the size of the lower file. */		lower_size_before_truncate =		    upper_size_to_lower_size(crypt_stat, i_size);		lower_size_after_truncate =		    upper_size_to_lower_size(crypt_stat, new_length);		if (lower_size_after_truncate < lower_size_before_truncate)			vmtruncate(lower_dentry->d_inode,				   lower_size_after_truncate);	}out_free:	if (ecryptfs_file_to_private(&fake_ecryptfs_file))		kmem_cache_free(ecryptfs_file_info_cache,				ecryptfs_file_to_private(&fake_ecryptfs_file));out:	return rc;}static intecryptfs_permission(struct inode *inode, int mask, struct nameidata *nd){	int rc;        if (nd) {		struct vfsmount *vfsmnt_save = nd->mnt;		struct dentry *dentry_save = nd->dentry;		nd->mnt = ecryptfs_dentry_to_lower_mnt(nd->dentry);		nd->dentry = ecryptfs_dentry_to_lower(nd->dentry);		rc = permission(ecryptfs_inode_to_lower(inode), mask, nd);		nd->mnt = vfsmnt_save;		nd->dentry = dentry_save;        } else		rc = permission(ecryptfs_inode_to_lower(inode), mask, NULL);        return rc;}/** * ecryptfs_setattr * @dentry: dentry handle to the inode to modify * @ia: Structure with flags of what to change and values * * Updates the metadata of an inode. If the update is to the size * i.e. truncation, then ecryptfs_truncate will handle the size modification * of both the ecryptfs inode and the lower inode. * * All other metadata changes will be passed right to the lower filesystem, * and we will just update our inode to look like the lower. */static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia){	int rc = 0;	struct dentry *lower_dentry;	struct inode *inode;	struct inode *lower_inode;	struct ecryptfs_crypt_stat *crypt_stat;	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;	if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))		ecryptfs_init_crypt_stat(crypt_stat);	inode = dentry->d_inode;	lower_inode = ecryptfs_inode_to_lower(inode);	lower_dentry = ecryptfs_dentry_to_lower(dentry);	mutex_lock(&crypt_stat->cs_mutex);	if (S_ISDIR(dentry->d_inode->i_mode))		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);	else if (S_ISREG(dentry->d_inode->i_mode)		 && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)		     || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {		struct ecryptfs_mount_crypt_stat *mount_crypt_stat;		mount_crypt_stat = &ecryptfs_superblock_to_private(			dentry->d_sb)->mount_crypt_stat;		rc = ecryptfs_read_metadata(dentry);		if (rc) {			if (!(mount_crypt_stat->flags			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {				rc = -EIO;				printk(KERN_WARNING "Attempt to read file that "				       "is not in a valid eCryptfs format, "				       "and plaintext passthrough mode is not "				       "enabled; returning -EIO\n");				mutex_unlock(&crypt_stat->cs_mutex);				goto out;			}			rc = 0;			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);			mutex_unlock(&crypt_stat->cs_mutex);			goto out;		}	}	mutex_unlock(&crypt_stat->cs_mutex);	if (ia->ia_valid & ATTR_SIZE) {		ecryptfs_printk(KERN_DEBUG,				"ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n",				ia->ia_valid, ATTR_SIZE);		rc = ecryptfs_truncate(dentry, ia->ia_size);		/* ecryptfs_truncate handles resizing of the lower file */		ia->ia_valid &= ~ATTR_SIZE;		ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n",				ia->ia_valid);		if (rc < 0)			goto out;	}	/*	 * mode change is for clearing setuid/setgid bits. Allow lower fs	 * to interpret this in its own way.	 */	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))		ia->ia_valid &= ~ATTR_MODE;	rc = notify_change(lower_dentry, ia);out:	fsstack_copy_attr_all(inode, lower_inode, NULL);	return rc;}intecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,		  size_t size, int flags){	int rc = 0;	struct dentry *lower_dentry;	lower_dentry = ecryptfs_dentry_to_lower(dentry);	if (!lower_dentry->d_inode->i_op->setxattr) {		rc = -ENOSYS;		goto out;	}	mutex_lock(&lower_dentry->d_inode->i_mutex);	rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, name, value,						   size, flags);	mutex_unlock(&lower_dentry->d_inode->i_mutex);out:	return rc;}ssize_tecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,			void *value, size_t size){	int rc = 0;	if (!lower_dentry->d_inode->i_op->getxattr) {		rc = -ENOSYS;		goto out;	}	mutex_lock(&lower_dentry->d_inode->i_mutex);	rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value,						   size);	mutex_unlock(&lower_dentry->d_inode->i_mutex);out:	return rc;}ssize_tecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,		  size_t size){	return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name,				       value, size);}static ssize_tecryptfs_listxattr(struct dentry *dentry, char *list, size_t size){	int rc = 0;	struct dentry *lower_dentry;	lower_dentry = ecryptfs_dentry_to_lower(dentry);	if (!lower_dentry->d_inode->i_op->listxattr) {		rc = -ENOSYS;		goto out;	}	mutex_lock(&lower_dentry->d_inode->i_mutex);	rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size);	mutex_unlock(&lower_dentry->d_inode->i_mutex);out:	return rc;}static int ecryptfs_removexattr(struct dentry *dentry, const char *name){	int rc = 0;	struct dentry *lower_dentry;	lower_dentry = ecryptfs_dentry_to_lower(dentry);	if (!lower_dentry->d_inode->i_op->removexattr) {		rc = -ENOSYS;		goto out;	}	mutex_lock(&lower_dentry->d_inode->i_mutex);	rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name);	mutex_unlock(&lower_dentry->d_inode->i_mutex);out:	return rc;}int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode){	if ((ecryptfs_inode_to_lower(inode)	     == (struct inode *)candidate_lower_inode))		return 1;	else		return 0;}int ecryptfs_inode_set(struct inode *inode, void *lower_inode){	ecryptfs_init_inode(inode, (struct inode *)lower_inode);	return 0;}const struct inode_operations ecryptfs_symlink_iops = {	.readlink = ecryptfs_readlink,	.follow_link = ecryptfs_follow_link,	.put_link = ecryptfs_put_link,	.permission = ecryptfs_permission,	.setattr = ecryptfs_setattr,	.setxattr = ecryptfs_setxattr,	.getxattr = ecryptfs_getxattr,	.listxattr = ecryptfs_listxattr,	.removexattr = ecryptfs_removexattr};const struct inode_operations ecryptfs_dir_iops = {	.create = ecryptfs_create,	.lookup = ecryptfs_lookup,	.link = ecryptfs_link,	.unlink = ecryptfs_unlink,	.symlink = ecryptfs_symlink,	.mkdir = ecryptfs_mkdir,	.rmdir = ecryptfs_rmdir,	.mknod = ecryptfs_mknod,	.rename = ecryptfs_rename,	.permission = ecryptfs_permission,	.setattr = ecryptfs_setattr,	.setxattr = ecryptfs_setxattr,	.getxattr = ecryptfs_getxattr,	.listxattr = ecryptfs_listxattr,	.removexattr = ecryptfs_removexattr};const struct inode_operations ecryptfs_main_iops = {	.permission = ecryptfs_permission,	.setattr = ecryptfs_setattr,	.setxattr = ecryptfs_setxattr,	.getxattr = ecryptfs_getxattr,	.listxattr = ecryptfs_listxattr,	.removexattr = ecryptfs_removexattr};

⌨️ 快捷键说明

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