linux/fs/ext4/symlink.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/ext4/symlink.c
   3 *
   4 * Only fast symlinks left here - the rest is done by generic code. AV, 1999
   5 *
   6 * Copyright (C) 1992, 1993, 1994, 1995
   7 * Remy Card (card@masi.ibp.fr)
   8 * Laboratoire MASI - Institut Blaise Pascal
   9 * Universite Pierre et Marie Curie (Paris VI)
  10 *
  11 *  from
  12 *
  13 *  linux/fs/minix/symlink.c
  14 *
  15 *  Copyright (C) 1991, 1992  Linus Torvalds
  16 *
  17 *  ext4 symlink handling code
  18 */
  19
  20#include <linux/fs.h>
  21#include <linux/namei.h>
  22#include "ext4.h"
  23#include "xattr.h"
  24
  25#ifdef CONFIG_EXT4_FS_ENCRYPTION
  26static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cookie)
  27{
  28        struct page *cpage = NULL;
  29        char *caddr, *paddr = NULL;
  30        struct ext4_str cstr, pstr;
  31        struct inode *inode = d_inode(dentry);
  32        struct ext4_encrypted_symlink_data *sd;
  33        loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
  34        int res;
  35        u32 plen, max_size = inode->i_sb->s_blocksize;
  36
  37        res = ext4_get_encryption_info(inode);
  38        if (res)
  39                return ERR_PTR(res);
  40
  41        if (ext4_inode_is_fast_symlink(inode)) {
  42                caddr = (char *) EXT4_I(inode)->i_data;
  43                max_size = sizeof(EXT4_I(inode)->i_data);
  44        } else {
  45                cpage = read_mapping_page(inode->i_mapping, 0, NULL);
  46                if (IS_ERR(cpage))
  47                        return ERR_CAST(cpage);
  48                caddr = kmap(cpage);
  49                caddr[size] = 0;
  50        }
  51
  52        /* Symlink is encrypted */
  53        sd = (struct ext4_encrypted_symlink_data *)caddr;
  54        cstr.name = sd->encrypted_path;
  55        cstr.len  = le32_to_cpu(sd->len);
  56        if ((cstr.len +
  57             sizeof(struct ext4_encrypted_symlink_data) - 1) >
  58            max_size) {
  59                /* Symlink data on the disk is corrupted */
  60                res = -EIO;
  61                goto errout;
  62        }
  63        plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ?
  64                EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len;
  65        paddr = kmalloc(plen + 1, GFP_NOFS);
  66        if (!paddr) {
  67                res = -ENOMEM;
  68                goto errout;
  69        }
  70        pstr.name = paddr;
  71        pstr.len = plen;
  72        res = _ext4_fname_disk_to_usr(inode, NULL, &cstr, &pstr);
  73        if (res < 0)
  74                goto errout;
  75        /* Null-terminate the name */
  76        if (res <= plen)
  77                paddr[res] = '\0';
  78        if (cpage) {
  79                kunmap(cpage);
  80                page_cache_release(cpage);
  81        }
  82        return *cookie = paddr;
  83errout:
  84        if (cpage) {
  85                kunmap(cpage);
  86                page_cache_release(cpage);
  87        }
  88        kfree(paddr);
  89        return ERR_PTR(res);
  90}
  91
  92const struct inode_operations ext4_encrypted_symlink_inode_operations = {
  93        .readlink       = generic_readlink,
  94        .follow_link    = ext4_encrypted_follow_link,
  95        .put_link       = kfree_put_link,
  96        .setattr        = ext4_setattr,
  97        .setxattr       = generic_setxattr,
  98        .getxattr       = generic_getxattr,
  99        .listxattr      = ext4_listxattr,
 100        .removexattr    = generic_removexattr,
 101};
 102#endif
 103
 104const struct inode_operations ext4_symlink_inode_operations = {
 105        .readlink       = generic_readlink,
 106        .follow_link    = page_follow_link_light,
 107        .put_link       = page_put_link,
 108        .setattr        = ext4_setattr,
 109        .setxattr       = generic_setxattr,
 110        .getxattr       = generic_getxattr,
 111        .listxattr      = ext4_listxattr,
 112        .removexattr    = generic_removexattr,
 113};
 114
 115const struct inode_operations ext4_fast_symlink_inode_operations = {
 116        .readlink       = generic_readlink,
 117        .follow_link    = simple_follow_link,
 118        .setattr        = ext4_setattr,
 119        .setxattr       = generic_setxattr,
 120        .getxattr       = generic_getxattr,
 121        .listxattr      = ext4_listxattr,
 122        .removexattr    = generic_removexattr,
 123};
 124