Import 2.3.26pre2
[davej-history.git] / fs / affs / symlink.c
blob18c03730f4789ac862dbffb93135427fb4f6f584
1 /*
2 * linux/fs/affs/symlink.c
4 * 1995 Hans-Joachim Widmaier - Modified for affs.
6 * Copyright (C) 1991, 1992 Linus Torvalds
8 * affs symlink handling code
9 */
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/malloc.h>
14 #include <linux/fs.h>
15 #include <linux/stat.h>
16 #include <linux/affs_fs.h>
17 #include <linux/amigaffs.h>
18 #include <asm/uaccess.h>
20 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 static int affs_readlink(struct dentry *, char *, int);
23 static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int);
25 struct inode_operations affs_symlink_inode_operations = {
26 NULL, /* no file-operations */
27 NULL, /* create */
28 NULL, /* lookup */
29 NULL, /* link */
30 NULL, /* unlink */
31 NULL, /* symlink */
32 NULL, /* mkdir */
33 NULL, /* rmdir */
34 NULL, /* mknod */
35 NULL, /* rename */
36 affs_readlink, /* readlink */
37 affs_follow_link, /* follow_link */
38 NULL, /* get_block */
39 NULL, /* readpage */
40 NULL, /* writepage */
41 NULL, /* flushpage */
42 NULL, /* truncate */
43 NULL, /* permission */
44 NULL, /* smap */
45 NULL /* revalidate */
48 static int
49 affs_readlink(struct dentry *dentry, char *buffer, int buflen)
51 struct inode *inode = dentry->d_inode;
52 struct buffer_head *bh;
53 struct slink_front *lf;
54 int i, j;
55 char c;
56 char lc;
57 char *pf;
59 pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
61 bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
62 if (!bh) {
63 affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
64 inode->i_ino);
65 return -EIO;
67 lf = (struct slink_front *)bh->b_data;
68 lc = 0;
69 i = 0;
70 j = 0;
71 pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
73 if (strchr(lf->symname,':')) { /* Handle assign or volume name */
74 while (i < buflen && (c = pf[i])) {
75 put_user(c,buffer++);
76 i++;
78 while (i < buflen && (c = lf->symname[j]) != ':') {
79 put_user(c,buffer++);
80 i++, j++;
82 if (i < buflen) {
83 put_user('/',buffer++);
84 i++, j++;
86 lc = '/';
88 while (i < buflen && (c = lf->symname[j])) {
89 if (c == '/' && lc == '/' && (i + 3 < buflen)) { /* parent dir */
90 put_user('.',buffer++);
91 put_user('.',buffer++);
92 i += 2;
94 put_user(c,buffer++);
95 lc = c;
96 i++, j++;
98 affs_brelse(bh);
99 return i;
102 static struct dentry *
103 affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
105 struct inode *inode = dentry->d_inode;
106 struct buffer_head *bh;
107 struct slink_front *lf;
108 char *buffer;
109 int i, j;
110 char c;
111 char lc;
112 char *pf;
114 pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
116 if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
117 dput(base);
118 return ERR_PTR(-ENOSPC);
120 bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
121 if (!bh) {
122 affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
123 inode->i_ino);
124 kfree(buffer);
125 dput(base);
126 return ERR_PTR(-EIO);
128 i = 0;
129 j = 0;
130 lf = (struct slink_front *)bh->b_data;
131 lc = 0;
132 pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
134 if (strchr(lf->symname,':')) { /* Handle assign or volume name */
135 while (i < 1023 && (c = pf[i]))
136 buffer[i++] = c;
137 while (i < 1023 && lf->symname[j] != ':')
138 buffer[i++] = lf->symname[j++];
139 if (i < 1023)
140 buffer[i++] = '/';
141 j++;
142 lc = '/';
144 while (i < 1023 && (c = lf->symname[j])) {
145 if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
146 buffer[i++] = '.';
147 buffer[i++] = '.';
149 buffer[i++] = c;
150 lc = c;
151 j++;
153 buffer[i] = '\0';
154 affs_brelse(bh);
155 base = lookup_dentry(buffer,base,follow);
156 kfree(buffer);
157 return base;