GNU Linux-libre 5.19-rc6-gnu
[releases.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_read_folio(struct file *file, struct folio *folio)
15 {
16         struct page *page = &folio->page;
17         struct buffer_head *bh;
18         struct inode *inode = page->mapping->host;
19         char *link = page_address(page);
20         struct slink_front *lf;
21         int                      i, j;
22         char                     c;
23         char                     lc;
24
25         pr_debug("get_link(ino=%lu)\n", inode->i_ino);
26
27         bh = affs_bread(inode->i_sb, inode->i_ino);
28         if (!bh)
29                 goto fail;
30         i  = 0;
31         j  = 0;
32         lf = (struct slink_front *)bh->b_data;
33         lc = 0;
34
35         if (strchr(lf->symname,':')) {  /* Handle assign or volume name */
36                 struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
37                 char *pf;
38                 spin_lock(&sbi->symlink_lock);
39                 pf = sbi->s_prefix ? sbi->s_prefix : "/";
40                 while (i < 1023 && (c = pf[i]))
41                         link[i++] = c;
42                 spin_unlock(&sbi->symlink_lock);
43                 while (i < 1023 && lf->symname[j] != ':')
44                         link[i++] = lf->symname[j++];
45                 if (i < 1023)
46                         link[i++] = '/';
47                 j++;
48                 lc = '/';
49         }
50         while (i < 1023 && (c = lf->symname[j])) {
51                 if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
52                         link[i++] = '.';
53                         link[i++] = '.';
54                 }
55                 link[i++] = c;
56                 lc = c;
57                 j++;
58         }
59         link[i] = '\0';
60         affs_brelse(bh);
61         SetPageUptodate(page);
62         unlock_page(page);
63         return 0;
64 fail:
65         SetPageError(page);
66         unlock_page(page);
67         return -EIO;
68 }
69
70 const struct address_space_operations affs_symlink_aops = {
71         .read_folio     = affs_symlink_read_folio,
72 };
73
74 const struct inode_operations affs_symlink_inode_operations = {
75         .get_link       = page_get_link,
76         .setattr        = affs_notify_change,
77 };