linux/fs/ext4/symlink.c
<<
>>
Prefs
   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};
 120