Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / fs / affs / symlink.c
1 /*
2  *  linux/fs/affs/symlink.c
3  *
4  *  1995  Hans-Joachim Widmaier - Modified for affs.
5  *
6  *  Copyright (C) 1991, 1992  Linus Torvalds
7  *
8  *  affs symlink handling code
9  */
10
11 #include "affs.h"
12
13 static int affs_symlink_readpage(struct file *file, struct page *page)
14 {
15         struct buffer_head *bh;
16         struct inode *inode = page->mapping->host;
17         char *link = kmap(page);
18         struct slink_front *lf;
19         int err;
20         int                      i, j;
21         char                     c;
22         char                     lc;
23
24         pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
25
26         err = -EIO;
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         kunmap(page);
63         unlock_page(page);
64         return 0;
65 fail:
66         SetPageError(page);
67         kunmap(page);
68         unlock_page(page);
69         return err;
70 }
71
72 const struct address_space_operations affs_symlink_aops = {
73         .readpage       = affs_symlink_readpage,
74 };
75
76 const struct inode_operations affs_symlink_inode_operations = {
77         .readlink       = generic_readlink,
78         .follow_link    = page_follow_link_light,
79         .put_link       = page_put_link,
80         .setattr        = affs_notify_change,
81 };