| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
 | 2 | /* | 
 | 3 |  *  linux/fs/affs/symlink.c | 
 | 4 |  * | 
 | 5 |  *  1995  Hans-Joachim Widmaier - Modified for affs. | 
 | 6 |  * | 
 | 7 |  *  Copyright (C) 1991, 1992  Linus Torvalds | 
 | 8 |  * | 
 | 9 |  *  affs symlink handling code | 
 | 10 |  */ | 
 | 11 |  | 
 | 12 | #include "affs.h" | 
 | 13 |  | 
 | 14 | static int affs_symlink_readpage(struct file *file, struct page *page) | 
 | 15 | { | 
 | 16 | 	struct buffer_head *bh; | 
 | 17 | 	struct inode *inode = page->mapping->host; | 
 | 18 | 	char *link = page_address(page); | 
 | 19 | 	struct slink_front *lf; | 
 | 20 | 	int			 i, j; | 
 | 21 | 	char			 c; | 
 | 22 | 	char			 lc; | 
 | 23 |  | 
 | 24 | 	pr_debug("get_link(ino=%lu)\n", inode->i_ino); | 
 | 25 |  | 
 | 26 | 	bh = affs_bread(inode->i_sb, inode->i_ino); | 
 | 27 | 	if (!bh) | 
 | 28 | 		goto fail; | 
 | 29 | 	i  = 0; | 
 | 30 | 	j  = 0; | 
 | 31 | 	lf = (struct slink_front *)bh->b_data; | 
 | 32 | 	lc = 0; | 
 | 33 |  | 
 | 34 | 	if (strchr(lf->symname,':')) {	/* Handle assign or volume name */ | 
 | 35 | 		struct affs_sb_info *sbi = AFFS_SB(inode->i_sb); | 
 | 36 | 		char *pf; | 
 | 37 | 		spin_lock(&sbi->symlink_lock); | 
 | 38 | 		pf = sbi->s_prefix ? sbi->s_prefix : "/"; | 
 | 39 | 		while (i < 1023 && (c = pf[i])) | 
 | 40 | 			link[i++] = c; | 
 | 41 | 		spin_unlock(&sbi->symlink_lock); | 
 | 42 | 		while (i < 1023 && lf->symname[j] != ':') | 
 | 43 | 			link[i++] = lf->symname[j++]; | 
 | 44 | 		if (i < 1023) | 
 | 45 | 			link[i++] = '/'; | 
 | 46 | 		j++; | 
 | 47 | 		lc = '/'; | 
 | 48 | 	} | 
 | 49 | 	while (i < 1023 && (c = lf->symname[j])) { | 
 | 50 | 		if (c == '/' && lc == '/' && i < 1020) {	/* parent dir */ | 
 | 51 | 			link[i++] = '.'; | 
 | 52 | 			link[i++] = '.'; | 
 | 53 | 		} | 
 | 54 | 		link[i++] = c; | 
 | 55 | 		lc = c; | 
 | 56 | 		j++; | 
 | 57 | 	} | 
 | 58 | 	link[i] = '\0'; | 
 | 59 | 	affs_brelse(bh); | 
 | 60 | 	SetPageUptodate(page); | 
 | 61 | 	unlock_page(page); | 
 | 62 | 	return 0; | 
 | 63 | fail: | 
 | 64 | 	SetPageError(page); | 
 | 65 | 	unlock_page(page); | 
 | 66 | 	return -EIO; | 
 | 67 | } | 
 | 68 |  | 
 | 69 | const struct address_space_operations affs_symlink_aops = { | 
 | 70 | 	.readpage	= affs_symlink_readpage, | 
 | 71 | }; | 
 | 72 |  | 
 | 73 | const struct inode_operations affs_symlink_inode_operations = { | 
 | 74 | 	.get_link	= page_get_link, | 
 | 75 | 	.setattr	= affs_notify_change, | 
 | 76 | }; |