0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "udfdecl.h"
0023 #include <linux/uaccess.h>
0024 #include <linux/errno.h>
0025 #include <linux/fs.h>
0026 #include <linux/time.h>
0027 #include <linux/mm.h>
0028 #include <linux/stat.h>
0029 #include <linux/pagemap.h>
0030 #include "udf_i.h"
0031
0032 static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
0033 int fromlen, unsigned char *to, int tolen)
0034 {
0035 struct pathComponent *pc;
0036 int elen = 0;
0037 int comp_len;
0038 unsigned char *p = to;
0039
0040
0041 tolen--;
0042 while (elen < fromlen) {
0043 pc = (struct pathComponent *)(from + elen);
0044 elen += sizeof(struct pathComponent);
0045 switch (pc->componentType) {
0046 case 1:
0047
0048
0049
0050
0051 if (pc->lengthComponentIdent > 0) {
0052 elen += pc->lengthComponentIdent;
0053 break;
0054 }
0055 fallthrough;
0056 case 2:
0057 if (tolen == 0)
0058 return -ENAMETOOLONG;
0059 p = to;
0060 *p++ = '/';
0061 tolen--;
0062 break;
0063 case 3:
0064 if (tolen < 3)
0065 return -ENAMETOOLONG;
0066 memcpy(p, "../", 3);
0067 p += 3;
0068 tolen -= 3;
0069 break;
0070 case 4:
0071 if (tolen < 2)
0072 return -ENAMETOOLONG;
0073 memcpy(p, "./", 2);
0074 p += 2;
0075 tolen -= 2;
0076
0077 break;
0078 case 5:
0079 elen += pc->lengthComponentIdent;
0080 if (elen > fromlen)
0081 return -EIO;
0082 comp_len = udf_get_filename(sb, pc->componentIdent,
0083 pc->lengthComponentIdent,
0084 p, tolen);
0085 if (comp_len < 0)
0086 return comp_len;
0087
0088 p += comp_len;
0089 tolen -= comp_len;
0090 if (tolen == 0)
0091 return -ENAMETOOLONG;
0092 *p++ = '/';
0093 tolen--;
0094 break;
0095 }
0096 }
0097 if (p > to + 1)
0098 p[-1] = '\0';
0099 else
0100 p[0] = '\0';
0101 return 0;
0102 }
0103
0104 static int udf_symlink_filler(struct file *file, struct folio *folio)
0105 {
0106 struct page *page = &folio->page;
0107 struct inode *inode = page->mapping->host;
0108 struct buffer_head *bh = NULL;
0109 unsigned char *symlink;
0110 int err;
0111 unsigned char *p = page_address(page);
0112 struct udf_inode_info *iinfo;
0113 uint32_t pos;
0114
0115
0116 if (inode->i_size > inode->i_sb->s_blocksize) {
0117 err = -ENAMETOOLONG;
0118 goto out_unmap;
0119 }
0120
0121 iinfo = UDF_I(inode);
0122 pos = udf_block_map(inode, 0);
0123
0124 down_read(&iinfo->i_data_sem);
0125 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
0126 symlink = iinfo->i_data + iinfo->i_lenEAttr;
0127 } else {
0128 bh = sb_bread(inode->i_sb, pos);
0129
0130 if (!bh) {
0131 err = -EIO;
0132 goto out_unlock_inode;
0133 }
0134
0135 symlink = bh->b_data;
0136 }
0137
0138 err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
0139 brelse(bh);
0140 if (err)
0141 goto out_unlock_inode;
0142
0143 up_read(&iinfo->i_data_sem);
0144 SetPageUptodate(page);
0145 unlock_page(page);
0146 return 0;
0147
0148 out_unlock_inode:
0149 up_read(&iinfo->i_data_sem);
0150 SetPageError(page);
0151 out_unmap:
0152 unlock_page(page);
0153 return err;
0154 }
0155
0156 static int udf_symlink_getattr(struct user_namespace *mnt_userns,
0157 const struct path *path, struct kstat *stat,
0158 u32 request_mask, unsigned int flags)
0159 {
0160 struct dentry *dentry = path->dentry;
0161 struct inode *inode = d_backing_inode(dentry);
0162 struct page *page;
0163
0164 generic_fillattr(&init_user_ns, inode, stat);
0165 page = read_mapping_page(inode->i_mapping, 0, NULL);
0166 if (IS_ERR(page))
0167 return PTR_ERR(page);
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 stat->size = strlen(page_address(page));
0178 put_page(page);
0179
0180 return 0;
0181 }
0182
0183
0184
0185
0186 const struct address_space_operations udf_symlink_aops = {
0187 .read_folio = udf_symlink_filler,
0188 };
0189
0190 const struct inode_operations udf_symlink_inode_operations = {
0191 .get_link = page_get_link,
0192 .getattr = udf_symlink_getattr,
0193 };