| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  linux/fs/affs/symlink.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  1995  Hans-Joachim Widmaier - Modified for affs. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (C) 1991, 1992  Linus Torvalds | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  affs symlink handling code | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "affs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int affs_symlink_readpage(struct file *file, struct page *page) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct buffer_head *bh; | 
					
						
							|  |  |  | 	struct inode *inode = page->mapping->host; | 
					
						
							|  |  |  | 	char *link = kmap(page); | 
					
						
							|  |  |  | 	struct slink_front *lf; | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 	int			 i, j; | 
					
						
							|  |  |  | 	char			 c; | 
					
						
							|  |  |  | 	char			 lc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = -EIO; | 
					
						
							|  |  |  | 	bh = affs_bread(inode->i_sb, inode->i_ino); | 
					
						
							|  |  |  | 	if (!bh) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 	i  = 0; | 
					
						
							|  |  |  | 	j  = 0; | 
					
						
							|  |  |  | 	lf = (struct slink_front *)bh->b_data; | 
					
						
							|  |  |  | 	lc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (strchr(lf->symname,':')) {	/* Handle assign or volume name */ | 
					
						
							| 
									
										
										
										
											2010-01-24 00:04:07 -05:00
										 |  |  | 		struct affs_sb_info *sbi = AFFS_SB(inode->i_sb); | 
					
						
							|  |  |  | 		char *pf; | 
					
						
							|  |  |  | 		spin_lock(&sbi->symlink_lock); | 
					
						
							|  |  |  | 		pf = sbi->s_prefix ? sbi->s_prefix : "/"; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		while (i < 1023 && (c = pf[i])) | 
					
						
							|  |  |  | 			link[i++] = c; | 
					
						
							| 
									
										
										
										
											2010-01-24 00:04:07 -05:00
										 |  |  | 		spin_unlock(&sbi->symlink_lock); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		while (i < 1023 && lf->symname[j] != ':') | 
					
						
							|  |  |  | 			link[i++] = lf->symname[j++]; | 
					
						
							|  |  |  | 		if (i < 1023) | 
					
						
							|  |  |  | 			link[i++] = '/'; | 
					
						
							|  |  |  | 		j++; | 
					
						
							|  |  |  | 		lc = '/'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	while (i < 1023 && (c = lf->symname[j])) { | 
					
						
							|  |  |  | 		if (c == '/' && lc == '/' && i < 1020) {	/* parent dir */ | 
					
						
							|  |  |  | 			link[i++] = '.'; | 
					
						
							|  |  |  | 			link[i++] = '.'; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		link[i++] = c; | 
					
						
							|  |  |  | 		lc = c; | 
					
						
							|  |  |  | 		j++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	link[i] = '\0'; | 
					
						
							|  |  |  | 	affs_brelse(bh); | 
					
						
							|  |  |  | 	SetPageUptodate(page); | 
					
						
							|  |  |  | 	kunmap(page); | 
					
						
							|  |  |  | 	unlock_page(page); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  | 	SetPageError(page); | 
					
						
							|  |  |  | 	kunmap(page); | 
					
						
							|  |  |  | 	unlock_page(page); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-28 04:26:44 -07:00
										 |  |  | const struct address_space_operations affs_symlink_aops = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.readpage	= affs_symlink_readpage, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-12 00:55:38 -08:00
										 |  |  | const struct inode_operations affs_symlink_inode_operations = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.readlink	= generic_readlink, | 
					
						
							|  |  |  | 	.follow_link	= page_follow_link_light, | 
					
						
							|  |  |  | 	.put_link	= page_put_link, | 
					
						
							|  |  |  | 	.setattr	= affs_notify_change, | 
					
						
							|  |  |  | }; |