symlink.c (2875B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * linux/fs/ext4/symlink.c 4 * 5 * Only fast symlinks left here - the rest is done by generic code. AV, 1999 6 * 7 * Copyright (C) 1992, 1993, 1994, 1995 8 * Remy Card (card@masi.ibp.fr) 9 * Laboratoire MASI - Institut Blaise Pascal 10 * Universite Pierre et Marie Curie (Paris VI) 11 * 12 * from 13 * 14 * linux/fs/minix/symlink.c 15 * 16 * Copyright (C) 1991, 1992 Linus Torvalds 17 * 18 * ext4 symlink handling code 19 */ 20 21#include <linux/fs.h> 22#include <linux/namei.h> 23#include "ext4.h" 24#include "xattr.h" 25 26static const char *ext4_encrypted_get_link(struct dentry *dentry, 27 struct inode *inode, 28 struct delayed_call *done) 29{ 30 struct buffer_head *bh = NULL; 31 const void *caddr; 32 unsigned int max_size; 33 const char *paddr; 34 35 if (!dentry) 36 return ERR_PTR(-ECHILD); 37 38 if (ext4_inode_is_fast_symlink(inode)) { 39 caddr = EXT4_I(inode)->i_data; 40 max_size = sizeof(EXT4_I(inode)->i_data); 41 } else { 42 bh = ext4_bread(NULL, inode, 0, 0); 43 if (IS_ERR(bh)) 44 return ERR_CAST(bh); 45 if (!bh) { 46 EXT4_ERROR_INODE(inode, "bad symlink."); 47 return ERR_PTR(-EFSCORRUPTED); 48 } 49 caddr = bh->b_data; 50 max_size = inode->i_sb->s_blocksize; 51 } 52 53 paddr = fscrypt_get_symlink(inode, caddr, max_size, done); 54 brelse(bh); 55 return paddr; 56} 57 58static int ext4_encrypted_symlink_getattr(struct user_namespace *mnt_userns, 59 const struct path *path, 60 struct kstat *stat, u32 request_mask, 61 unsigned int query_flags) 62{ 63 ext4_getattr(mnt_userns, path, stat, request_mask, query_flags); 64 65 return fscrypt_symlink_getattr(path, stat); 66} 67 68static void ext4_free_link(void *bh) 69{ 70 brelse(bh); 71} 72 73static const char *ext4_get_link(struct dentry *dentry, struct inode *inode, 74 struct delayed_call *callback) 75{ 76 struct buffer_head *bh; 77 78 if (!dentry) { 79 bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT); 80 if (IS_ERR(bh)) 81 return ERR_CAST(bh); 82 if (!bh || !ext4_buffer_uptodate(bh)) 83 return ERR_PTR(-ECHILD); 84 } else { 85 bh = ext4_bread(NULL, inode, 0, 0); 86 if (IS_ERR(bh)) 87 return ERR_CAST(bh); 88 if (!bh) { 89 EXT4_ERROR_INODE(inode, "bad symlink."); 90 return ERR_PTR(-EFSCORRUPTED); 91 } 92 } 93 94 set_delayed_call(callback, ext4_free_link, bh); 95 nd_terminate_link(bh->b_data, inode->i_size, 96 inode->i_sb->s_blocksize - 1); 97 return bh->b_data; 98} 99 100const struct inode_operations ext4_encrypted_symlink_inode_operations = { 101 .get_link = ext4_encrypted_get_link, 102 .setattr = ext4_setattr, 103 .getattr = ext4_encrypted_symlink_getattr, 104 .listxattr = ext4_listxattr, 105}; 106 107const struct inode_operations ext4_symlink_inode_operations = { 108 .get_link = ext4_get_link, 109 .setattr = ext4_setattr, 110 .getattr = ext4_getattr, 111 .listxattr = ext4_listxattr, 112}; 113 114const struct inode_operations ext4_fast_symlink_inode_operations = { 115 .get_link = simple_get_link, 116 .setattr = ext4_setattr, 117 .getattr = ext4_getattr, 118 .listxattr = ext4_listxattr, 119};