18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/affs/symlink.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * 1995 Hans-Joachim Widmaier - Modified for affs. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * affs symlink handling code 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "affs.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic int affs_symlink_readpage(struct file *file, struct page *page) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci struct buffer_head *bh; 178c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 188c2ecf20Sopenharmony_ci char *link = page_address(page); 198c2ecf20Sopenharmony_ci struct slink_front *lf; 208c2ecf20Sopenharmony_ci int i, j; 218c2ecf20Sopenharmony_ci char c; 228c2ecf20Sopenharmony_ci char lc; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci pr_debug("get_link(ino=%lu)\n", inode->i_ino); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci bh = affs_bread(inode->i_sb, inode->i_ino); 278c2ecf20Sopenharmony_ci if (!bh) 288c2ecf20Sopenharmony_ci goto fail; 298c2ecf20Sopenharmony_ci i = 0; 308c2ecf20Sopenharmony_ci j = 0; 318c2ecf20Sopenharmony_ci lf = (struct slink_front *)bh->b_data; 328c2ecf20Sopenharmony_ci lc = 0; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (strchr(lf->symname,':')) { /* Handle assign or volume name */ 358c2ecf20Sopenharmony_ci struct affs_sb_info *sbi = AFFS_SB(inode->i_sb); 368c2ecf20Sopenharmony_ci char *pf; 378c2ecf20Sopenharmony_ci spin_lock(&sbi->symlink_lock); 388c2ecf20Sopenharmony_ci pf = sbi->s_prefix ? sbi->s_prefix : "/"; 398c2ecf20Sopenharmony_ci while (i < 1023 && (c = pf[i])) 408c2ecf20Sopenharmony_ci link[i++] = c; 418c2ecf20Sopenharmony_ci spin_unlock(&sbi->symlink_lock); 428c2ecf20Sopenharmony_ci while (i < 1023 && lf->symname[j] != ':') 438c2ecf20Sopenharmony_ci link[i++] = lf->symname[j++]; 448c2ecf20Sopenharmony_ci if (i < 1023) 458c2ecf20Sopenharmony_ci link[i++] = '/'; 468c2ecf20Sopenharmony_ci j++; 478c2ecf20Sopenharmony_ci lc = '/'; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci while (i < 1023 && (c = lf->symname[j])) { 508c2ecf20Sopenharmony_ci if (c == '/' && lc == '/' && i < 1020) { /* parent dir */ 518c2ecf20Sopenharmony_ci link[i++] = '.'; 528c2ecf20Sopenharmony_ci link[i++] = '.'; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci link[i++] = c; 558c2ecf20Sopenharmony_ci lc = c; 568c2ecf20Sopenharmony_ci j++; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci link[i] = '\0'; 598c2ecf20Sopenharmony_ci affs_brelse(bh); 608c2ecf20Sopenharmony_ci SetPageUptodate(page); 618c2ecf20Sopenharmony_ci unlock_page(page); 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_cifail: 648c2ecf20Sopenharmony_ci SetPageError(page); 658c2ecf20Sopenharmony_ci unlock_page(page); 668c2ecf20Sopenharmony_ci return -EIO; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciconst struct address_space_operations affs_symlink_aops = { 708c2ecf20Sopenharmony_ci .readpage = affs_symlink_readpage, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciconst struct inode_operations affs_symlink_inode_operations = { 748c2ecf20Sopenharmony_ci .get_link = page_get_link, 758c2ecf20Sopenharmony_ci .setattr = affs_notify_change, 768c2ecf20Sopenharmony_ci}; 77