LCOV - code coverage report
Current view: top level - fs/ext4 - symlink.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 18 43 41.9 %
Date: 2023-07-31 20:08:34 Functions: 2 4 50.0 %

          Line data    Source code
       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             : 
      26           0 : static const char *ext4_encrypted_get_link(struct dentry *dentry,
      27             :                                            struct inode *inode,
      28             :                                            struct delayed_call *done)
      29             : {
      30           0 :         struct buffer_head *bh = NULL;
      31           0 :         const void *caddr;
      32           0 :         unsigned int max_size;
      33           0 :         const char *paddr;
      34             : 
      35           0 :         if (!dentry)
      36             :                 return ERR_PTR(-ECHILD);
      37             : 
      38           0 :         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           0 :                 bh = ext4_bread(NULL, inode, 0, 0);
      43           0 :                 if (IS_ERR(bh))
      44             :                         return ERR_CAST(bh);
      45           0 :                 if (!bh) {
      46           0 :                         EXT4_ERROR_INODE(inode, "bad symlink.");
      47           0 :                         return ERR_PTR(-EFSCORRUPTED);
      48             :                 }
      49             :                 caddr = bh->b_data;
      50             :                 max_size = inode->i_sb->s_blocksize;
      51             :         }
      52             : 
      53           0 :         paddr = fscrypt_get_symlink(inode, caddr, max_size, done);
      54           0 :         brelse(bh);
      55             :         return paddr;
      56             : }
      57             : 
      58           0 : static int ext4_encrypted_symlink_getattr(struct mnt_idmap *idmap,
      59             :                                           const struct path *path,
      60             :                                           struct kstat *stat, u32 request_mask,
      61             :                                           unsigned int query_flags)
      62             : {
      63           0 :         ext4_getattr(idmap, path, stat, request_mask, query_flags);
      64             : 
      65           0 :         return fscrypt_symlink_getattr(path, stat);
      66             : }
      67             : 
      68       14337 : static void ext4_free_link(void *bh)
      69             : {
      70       14337 :         brelse(bh);
      71       14336 : }
      72             : 
      73       14337 : static const char *ext4_get_link(struct dentry *dentry, struct inode *inode,
      74             :                                  struct delayed_call *callback)
      75             : {
      76       14337 :         struct buffer_head *bh;
      77       14337 :         char *inline_link;
      78             : 
      79             :         /*
      80             :          * Create a new inlined symlink is not supported, just provide a
      81             :          * method to read the leftovers.
      82             :          */
      83       14337 :         if (ext4_has_inline_data(inode)) {
      84           0 :                 if (!dentry)
      85             :                         return ERR_PTR(-ECHILD);
      86             : 
      87           0 :                 inline_link = ext4_read_inline_link(inode);
      88           0 :                 if (!IS_ERR(inline_link))
      89           0 :                         set_delayed_call(callback, kfree_link, inline_link);
      90           0 :                 return inline_link;
      91             :         }
      92             : 
      93       14337 :         if (!dentry) {
      94        1367 :                 bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT);
      95        1367 :                 if (IS_ERR(bh))
      96             :                         return ERR_CAST(bh);
      97        1367 :                 if (!bh || !ext4_buffer_uptodate(bh))
      98           0 :                         return ERR_PTR(-ECHILD);
      99             :         } else {
     100       12970 :                 bh = ext4_bread(NULL, inode, 0, 0);
     101       12970 :                 if (IS_ERR(bh))
     102             :                         return ERR_CAST(bh);
     103       12970 :                 if (!bh) {
     104           0 :                         EXT4_ERROR_INODE(inode, "bad symlink.");
     105           0 :                         return ERR_PTR(-EFSCORRUPTED);
     106             :                 }
     107             :         }
     108             : 
     109       14337 :         set_delayed_call(callback, ext4_free_link, bh);
     110       14337 :         nd_terminate_link(bh->b_data, inode->i_size,
     111       14337 :                           inode->i_sb->s_blocksize - 1);
     112       14337 :         return bh->b_data;
     113             : }
     114             : 
     115             : const struct inode_operations ext4_encrypted_symlink_inode_operations = {
     116             :         .get_link       = ext4_encrypted_get_link,
     117             :         .setattr        = ext4_setattr,
     118             :         .getattr        = ext4_encrypted_symlink_getattr,
     119             :         .listxattr      = ext4_listxattr,
     120             : };
     121             : 
     122             : const struct inode_operations ext4_symlink_inode_operations = {
     123             :         .get_link       = ext4_get_link,
     124             :         .setattr        = ext4_setattr,
     125             :         .getattr        = ext4_getattr,
     126             :         .listxattr      = ext4_listxattr,
     127             : };
     128             : 
     129             : const struct inode_operations ext4_fast_symlink_inode_operations = {
     130             :         .get_link       = simple_get_link,
     131             :         .setattr        = ext4_setattr,
     132             :         .getattr        = ext4_getattr,
     133             :         .listxattr      = ext4_listxattr,
     134             : };

Generated by: LCOV version 1.14