This source file includes following definitions.
- affs_follow_link
- affs_conv_path
- affs_readlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <asm/segment.h>
16
17 #include <linux/errno.h>
18 #include <linux/sched.h>
19 #include <linux/fs.h>
20 #include <linux/stat.h>
21 #include <linux/malloc.h>
22 #include <linux/affs_fs.h>
23
24 #include "amigaffs.h"
25
26 static int affs_readlink(struct inode *, char *, int);
27 static int affs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
28
29
30
31
32 struct inode_operations affs_symlink_inode_operations = {
33 NULL,
34 NULL,
35 NULL,
36 NULL,
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41 NULL,
42 NULL,
43 affs_readlink,
44 affs_follow_link,
45 NULL,
46 NULL,
47 NULL
48 };
49
50 static int affs_follow_link(struct inode * dir, struct inode * inode,
51 int flag, int mode, struct inode ** res_inode)
52 {
53 int error;
54 char * pnt;
55 struct buffer_head *bh;
56 struct symlink_front *sy_data;
57
58 if (!dir) {
59 dir = current->fs->root;
60 dir->i_count++;
61 }
62 if (!inode) {
63 iput(dir);
64 *res_inode = NULL;
65 return -ENOENT;
66 }
67 if (!S_ISLNK(inode->i_mode)) {
68 iput(dir);
69 *res_inode = inode;
70 return 0;
71 }
72 if (current->link_count > 5) {
73 iput(dir);
74 iput(inode);
75 *res_inode = NULL;
76 return -ELOOP;
77 }
78 if (!(bh = affs_pread(inode,inode->i_ino,(void **)&sy_data))) {
79 printk("affs: unable to read block %ld",inode->i_ino);
80 return 0;
81 }
82
83 pnt = sy_data->symname;
84 iput(inode);
85 current->link_count++;
86 error = open_namei(pnt,flag,mode,res_inode,dir);
87 current->link_count--;
88 brelse(bh);
89 return error;
90 }
91
92 static char *affs_conv_path(char *affs_path)
93 {
94 static char unix_path[1024]="/";
95 int up,ap;
96 char dp,slash;
97
98
99 dp=1;
100 slash=1;
101 ap=0;
102 up=1;
103 if (affs_path[0] == 0)
104 unix_path[up++]='.';
105 while ((up < 1020) && (affs_path[ap]!=0))
106 {
107 switch (affs_path[ap]) {
108 case ':':
109 if (dp == 0) {
110 slash=0;
111 unix_path[up++]=':';
112 }
113 else {
114 dp=0;
115 slash=1;
116 unix_path[up++]='/';
117 }
118 break;
119 case '/':
120 if (slash==0) {
121 slash=1;
122 unix_path[up++]='/';
123 }
124 else {
125 unix_path[up++]='.';
126 unix_path[up++]='.';
127 unix_path[up++]='/';
128 }
129 break;
130 default:
131 slash=0;
132 unix_path[up++]=affs_path[ap];
133 break;
134 }
135 ap++;
136 }
137 unix_path[up]=0;
138 return unix_path+dp;
139 }
140
141
142 static int affs_readlink(struct inode * inode, char * buffer, int buflen)
143 {
144 char * pnt;
145 int i;
146 char c;
147 struct buffer_head *bh;
148 struct symlink_front *sy_data;
149
150 if (!S_ISLNK(inode->i_mode)) {
151 iput(inode);
152 return -EINVAL;
153 }
154
155 if (buflen > 1023)
156 buflen = 1023;
157
158 if (!(bh = affs_pread(inode,inode->i_ino,(void **)&sy_data))) {
159 printk("affs: unable to read block %ld\n",inode->i_ino);
160 return -ENOENT;
161 }
162
163 iput(inode);
164
165 pnt = sy_data->symname;
166 if (inode->i_sb->u.affs_sb.s_options.conv_links != 0)
167 pnt = affs_conv_path(pnt);
168
169 i = 0;
170
171 while (i<buflen && (c = pnt[i])) {
172 i++;
173 put_fs_byte(c,buffer++);
174 }
175
176 brelse(bh);
177
178 return i;
179 }