xref: /kernel/linux/linux-5.10/fs/affs/symlink.c (revision 8c2ecf20)
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