Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[linux-3.10.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         char                    *pf;
24
25         pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
26
27         err = -EIO;
28         bh = affs_bread(inode->i_sb, inode->i_ino);
29         if (!bh)
30                 goto fail;
31         i  = 0;
32         j  = 0;
33         lf = (struct slink_front *)bh->b_data;
34         lc = 0;
35         pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
36
37         if (strchr(lf->symname,':')) {  /* Handle assign or volume name */
38                 while (i < 1023 && (c = pf[i]))
39                         link[i++] = c;
40                 while (i < 1023 && lf->symname[j] != ':')
41                         link[i++] = lf->symname[j++];
42                 if (i < 1023)
43                         link[i++] = '/';
44                 j++;
45                 lc = '/';
46         }
47         while (i < 1023 && (c = lf->symname[j])) {
48                 if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
49                         link[i++] = '.';
50                         link[i++] = '.';
51                 }
52                 link[i++] = c;
53                 lc = c;
54                 j++;
55         }
56         link[i] = '\0';
57         affs_brelse(bh);
58         SetPageUptodate(page);
59         kunmap(page);
60         unlock_page(page);
61         return 0;
62 fail:
63         SetPageError(page);
64         kunmap(page);
65         unlock_page(page);
66         return err;
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         .readlink       = generic_readlink,
75         .follow_link    = page_follow_link_light,
76         .put_link       = page_put_link,
77         .setattr        = affs_notify_change,
78 };