Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/fs/ext4/symlink.c
0004  *
0005  * Only fast symlinks left here - the rest is done by generic code. AV, 1999
0006  *
0007  * Copyright (C) 1992, 1993, 1994, 1995
0008  * Remy Card (card@masi.ibp.fr)
0009  * Laboratoire MASI - Institut Blaise Pascal
0010  * Universite Pierre et Marie Curie (Paris VI)
0011  *
0012  *  from
0013  *
0014  *  linux/fs/minix/symlink.c
0015  *
0016  *  Copyright (C) 1991, 1992  Linus Torvalds
0017  *
0018  *  ext4 symlink handling code
0019  */
0020 
0021 #include <linux/fs.h>
0022 #include <linux/namei.h>
0023 #include "ext4.h"
0024 #include "xattr.h"
0025 
0026 static const char *ext4_encrypted_get_link(struct dentry *dentry,
0027                        struct inode *inode,
0028                        struct delayed_call *done)
0029 {
0030     struct buffer_head *bh = NULL;
0031     const void *caddr;
0032     unsigned int max_size;
0033     const char *paddr;
0034 
0035     if (!dentry)
0036         return ERR_PTR(-ECHILD);
0037 
0038     if (ext4_inode_is_fast_symlink(inode)) {
0039         caddr = EXT4_I(inode)->i_data;
0040         max_size = sizeof(EXT4_I(inode)->i_data);
0041     } else {
0042         bh = ext4_bread(NULL, inode, 0, 0);
0043         if (IS_ERR(bh))
0044             return ERR_CAST(bh);
0045         if (!bh) {
0046             EXT4_ERROR_INODE(inode, "bad symlink.");
0047             return ERR_PTR(-EFSCORRUPTED);
0048         }
0049         caddr = bh->b_data;
0050         max_size = inode->i_sb->s_blocksize;
0051     }
0052 
0053     paddr = fscrypt_get_symlink(inode, caddr, max_size, done);
0054     brelse(bh);
0055     return paddr;
0056 }
0057 
0058 static int ext4_encrypted_symlink_getattr(struct user_namespace *mnt_userns,
0059                       const struct path *path,
0060                       struct kstat *stat, u32 request_mask,
0061                       unsigned int query_flags)
0062 {
0063     ext4_getattr(mnt_userns, path, stat, request_mask, query_flags);
0064 
0065     return fscrypt_symlink_getattr(path, stat);
0066 }
0067 
0068 static void ext4_free_link(void *bh)
0069 {
0070     brelse(bh);
0071 }
0072 
0073 static const char *ext4_get_link(struct dentry *dentry, struct inode *inode,
0074                  struct delayed_call *callback)
0075 {
0076     struct buffer_head *bh;
0077     char *inline_link;
0078 
0079     /*
0080      * Create a new inlined symlink is not supported, just provide a
0081      * method to read the leftovers.
0082      */
0083     if (ext4_has_inline_data(inode)) {
0084         if (!dentry)
0085             return ERR_PTR(-ECHILD);
0086 
0087         inline_link = ext4_read_inline_link(inode);
0088         if (!IS_ERR(inline_link))
0089             set_delayed_call(callback, kfree_link, inline_link);
0090         return inline_link;
0091     }
0092 
0093     if (!dentry) {
0094         bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT);
0095         if (IS_ERR(bh))
0096             return ERR_CAST(bh);
0097         if (!bh || !ext4_buffer_uptodate(bh))
0098             return ERR_PTR(-ECHILD);
0099     } else {
0100         bh = ext4_bread(NULL, inode, 0, 0);
0101         if (IS_ERR(bh))
0102             return ERR_CAST(bh);
0103         if (!bh) {
0104             EXT4_ERROR_INODE(inode, "bad symlink.");
0105             return ERR_PTR(-EFSCORRUPTED);
0106         }
0107     }
0108 
0109     set_delayed_call(callback, ext4_free_link, bh);
0110     nd_terminate_link(bh->b_data, inode->i_size,
0111               inode->i_sb->s_blocksize - 1);
0112     return bh->b_data;
0113 }
0114 
0115 const struct inode_operations ext4_encrypted_symlink_inode_operations = {
0116     .get_link   = ext4_encrypted_get_link,
0117     .setattr    = ext4_setattr,
0118     .getattr    = ext4_encrypted_symlink_getattr,
0119     .listxattr  = ext4_listxattr,
0120 };
0121 
0122 const struct inode_operations ext4_symlink_inode_operations = {
0123     .get_link   = ext4_get_link,
0124     .setattr    = ext4_setattr,
0125     .getattr    = ext4_getattr,
0126     .listxattr  = ext4_listxattr,
0127 };
0128 
0129 const struct inode_operations ext4_fast_symlink_inode_operations = {
0130     .get_link   = simple_get_link,
0131     .setattr    = ext4_setattr,
0132     .getattr    = ext4_getattr,
0133     .listxattr  = ext4_listxattr,
0134 };