Linux 6.9-rc1
[linux-2.6-microblaze.git] / fs / affs / symlink.c
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 };