Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) };