1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/affs/symlink.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * 1995 Hans-Joachim Widmaier - Modified for affs.
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * affs symlink handling code
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds #include "affs.h"
131da177e4SLinus Torvalds
affs_symlink_read_folio(struct file * file,struct folio * folio)141b6f3c87SMatthew Wilcox (Oracle) static int affs_symlink_read_folio(struct file *file, struct folio *folio)
151da177e4SLinus Torvalds {
161da177e4SLinus Torvalds struct buffer_head *bh;
17*41a638a1SMatthew Wilcox (Oracle) struct inode *inode = folio->mapping->host;
18*41a638a1SMatthew Wilcox (Oracle) char *link = folio_address(folio);
191da177e4SLinus Torvalds struct slink_front *lf;
201da177e4SLinus Torvalds int i, j;
211da177e4SLinus Torvalds char c;
221da177e4SLinus Torvalds char lc;
231da177e4SLinus Torvalds
246b255391SAl Viro pr_debug("get_link(ino=%lu)\n", inode->i_ino);
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds bh = affs_bread(inode->i_sb, inode->i_ino);
271da177e4SLinus Torvalds if (!bh)
281da177e4SLinus Torvalds goto fail;
291da177e4SLinus Torvalds i = 0;
301da177e4SLinus Torvalds j = 0;
311da177e4SLinus Torvalds lf = (struct slink_front *)bh->b_data;
321da177e4SLinus Torvalds lc = 0;
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds if (strchr(lf->symname,':')) { /* Handle assign or volume name */
3529333920SAl Viro struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
3629333920SAl Viro char *pf;
3729333920SAl Viro spin_lock(&sbi->symlink_lock);
3829333920SAl Viro pf = sbi->s_prefix ? sbi->s_prefix : "/";
391da177e4SLinus Torvalds while (i < 1023 && (c = pf[i]))
401da177e4SLinus Torvalds link[i++] = c;
4129333920SAl Viro spin_unlock(&sbi->symlink_lock);
421da177e4SLinus Torvalds while (i < 1023 && lf->symname[j] != ':')
431da177e4SLinus Torvalds link[i++] = lf->symname[j++];
441da177e4SLinus Torvalds if (i < 1023)
451da177e4SLinus Torvalds link[i++] = '/';
461da177e4SLinus Torvalds j++;
471da177e4SLinus Torvalds lc = '/';
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds while (i < 1023 && (c = lf->symname[j])) {
501da177e4SLinus Torvalds if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
511da177e4SLinus Torvalds link[i++] = '.';
521da177e4SLinus Torvalds link[i++] = '.';
531da177e4SLinus Torvalds }
541da177e4SLinus Torvalds link[i++] = c;
551da177e4SLinus Torvalds lc = c;
561da177e4SLinus Torvalds j++;
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds link[i] = '\0';
591da177e4SLinus Torvalds affs_brelse(bh);
60*41a638a1SMatthew Wilcox (Oracle) folio_mark_uptodate(folio);
61*41a638a1SMatthew Wilcox (Oracle) folio_unlock(folio);
621da177e4SLinus Torvalds return 0;
631da177e4SLinus Torvalds fail:
64*41a638a1SMatthew Wilcox (Oracle) folio_unlock(folio);
65196a4f82SFabian Frederick return -EIO;
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds
68f5e54d6eSChristoph Hellwig const struct address_space_operations affs_symlink_aops = {
691b6f3c87SMatthew Wilcox (Oracle) .read_folio = affs_symlink_read_folio,
701da177e4SLinus Torvalds };
711da177e4SLinus Torvalds
72754661f1SArjan van de Ven const struct inode_operations affs_symlink_inode_operations = {
736b255391SAl Viro .get_link = page_get_link,
741da177e4SLinus Torvalds .setattr = affs_notify_change,
751da177e4SLinus Torvalds };
76