^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * symlink.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Symlink handling routines for the OSTA-UDF(tm) filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is distributed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License (GPL). Copies of the GPL can be obtained from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * ftp://prep.ai.mit.edu/pub/gnu/GPL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Each contributing author retains all rights to their own work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * (C) 1998-2001 Ben Fennema
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * (C) 1999 Stelias Computing Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * HISTORY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 04/16/99 blf Created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "udfdecl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "udf_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int fromlen, unsigned char *to, int tolen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct pathComponent *pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int elen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int comp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned char *p = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Reserve one byte for terminating \0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) tolen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) while (elen < fromlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) pc = (struct pathComponent *)(from + elen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) elen += sizeof(struct pathComponent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) switch (pc->componentType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Symlink points to some place which should be agreed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * upon between originator and receiver of the media. Ignore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (pc->lengthComponentIdent > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) elen += pc->lengthComponentIdent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (tolen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) p = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *p++ = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) tolen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (tolen < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) memcpy(p, "../", 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) p += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) tolen -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (tolen < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) memcpy(p, "./", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) p += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) tolen -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* that would be . - just ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) elen += pc->lengthComponentIdent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (elen > fromlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) comp_len = udf_get_filename(sb, pc->componentIdent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pc->lengthComponentIdent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) p, tolen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (comp_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return comp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) p += comp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) tolen -= comp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (tolen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *p++ = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) tolen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (p > to + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) p[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) p[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int udf_symlink_filler(struct file *file, struct page *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct inode *inode = page->mapping->host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned char *symlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned char *p = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct udf_inode_info *iinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) uint32_t pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* We don't support symlinks longer than one block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (inode->i_size > inode->i_sb->s_blocksize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) err = -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) iinfo = UDF_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) pos = udf_block_map(inode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) down_read(&iinfo->i_data_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) symlink = iinfo->i_data + iinfo->i_lenEAttr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bh = sb_bread(inode->i_sb, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) goto out_unlock_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) symlink = bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto out_unlock_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) up_read(&iinfo->i_data_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) SetPageUptodate(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) out_unlock_inode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) up_read(&iinfo->i_data_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) SetPageError(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) out_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int udf_symlink_getattr(const struct path *path, struct kstat *stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u32 request_mask, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct dentry *dentry = path->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct inode *inode = d_backing_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) generic_fillattr(inode, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) page = read_mapping_page(inode->i_mapping, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (IS_ERR(page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return PTR_ERR(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * UDF uses non-trivial encoding of symlinks so i_size does not match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * number of characters reported by readlink(2) which apparently some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * applications expect. Also POSIX says that "The value returned in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * st_size field shall be the length of the contents of the symbolic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * link, and shall not count a trailing null if one is present." So
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * let's report the length of string returned by readlink(2) for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * st_size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) stat->size = strlen(page_address(page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * symlinks can't do much...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) const struct address_space_operations udf_symlink_aops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .readpage = udf_symlink_filler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) const struct inode_operations udf_symlink_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .get_link = page_get_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .getattr = udf_symlink_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };