ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-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 <linux/errno.h>
12 #include <linux/fs.h>
13 #include <linux/stat.h>
14 #include <linux/affs_fs.h>
15 #include <linux/amigaffs.h>
16 #include <linux/pagemap.h>
17 #include <linux/smp_lock.h>
18 #include <linux/buffer_head.h>
19
20 static int affs_symlink_readpage(struct file *file, struct page *page)
21 {
22         struct buffer_head *bh;
23         struct inode *inode = page->mapping->host;
24         char *link = kmap(page);
25         struct slink_front *lf;
26         int err;
27         int                      i, j;
28         char                     c;
29         char                     lc;
30         char                    *pf;
31
32         pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
33
34         err = -EIO;
35         bh = affs_bread(inode->i_sb, inode->i_ino);
36         if (!bh)
37                 goto fail;
38         i  = 0;
39         j  = 0;
40         lf = (struct slink_front *)bh->b_data;
41         lc = 0;
42         pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
43
44         if (strchr(lf->symname,':')) {  /* Handle assign or volume name */
45                 while (i < 1023 && (c = pf[i]))
46                         link[i++] = c;
47                 while (i < 1023 && lf->symname[j] != ':')
48                         link[i++] = lf->symname[j++];
49                 if (i < 1023)
50                         link[i++] = '/';
51                 j++;
52                 lc = '/';
53         }
54         while (i < 1023 && (c = lf->symname[j])) {
55                 if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
56                         link[i++] = '.';
57                         link[i++] = '.';
58                 }
59                 link[i++] = c;
60                 lc = c;
61                 j++;
62         }
63         link[i] = '\0';
64         affs_brelse(bh);
65         SetPageUptodate(page);
66         kunmap(page);
67         unlock_page(page);
68         return 0;
69 fail:
70         SetPageError(page);
71         kunmap(page);
72         unlock_page(page);
73         return err;
74 }
75
76 struct address_space_operations affs_symlink_aops = {
77         .readpage       = affs_symlink_readpage,
78 };
79
80 struct inode_operations affs_symlink_inode_operations = {
81         .readlink       = page_readlink,
82         .follow_link    = page_follow_link,
83         .setattr        = affs_notify_change,
84 };