3 * Copyright (C) 2002 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
8 * LUFS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * LUFS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/version.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <linux/socket.h>
28 #include <linux/smp_lock.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
38 static char failed_link[] = "invalid";
40 static int lu_readlink(struct dentry *dentry, char *buffer, int bufflen)
42 struct server_slot *slot;
43 struct iovec siov, riov;
45 char *cc = failed_link;
49 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
50 return vfs_readlink(dentry, buffer, bufflen, cc);
52 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
53 WARN("lu_getname failed!\n");
57 siov.iov_base = slot->s_buf;
58 siov.iov_len = strlen(slot->s_buf) + 1;
59 riov.iov_base = &slot->s_buf[LU_MAXPATHLEN];
60 riov.iov_len = LU_MAXPATHLEN;
62 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_READLINK, &siov, 1, &riov, 1)) < 0)
66 TRACE("read_link failed.\n");
71 cc = &slot->s_buf[LU_MAXPATHLEN];
73 TRACE("response: %s\n", cc);
76 if(GET_INFO(dentry->d_sb)->rootlen){
77 if(strncmp(GET_INFO(dentry->d_sb)->root, cc, GET_INFO(dentry->d_sb)->rootlen)){
78 WARN("symlink outside mounted root!");
82 cc += GET_INFO(dentry->d_sb)->rootlen;
85 lu_xlate_symlink(slot->s_buf, slot->s_buf + LU_MAXPATHLEN, slot->s_buf);
94 res = vfs_readlink(dentry, buffer, bufflen, cc);
102 static int lu_followlink(struct dentry *dentry, struct nameidata *nd)
104 struct server_slot *slot;
105 struct iovec siov, riov;
107 char *cc = failed_link;
112 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
113 return vfs_follow_link(nd, cc);
116 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
117 WARN("lu_getname failed!\n");
121 siov.iov_base = slot->s_buf;
122 siov.iov_len = strlen(slot->s_buf) + 1;
123 riov.iov_base = &slot->s_buf[LU_MAXPATHLEN];
124 riov.iov_len = LU_MAXPATHLEN;
126 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_READLINK, &siov, 1, &riov, 1)) < 0)
130 TRACE("read_link failed.\n");
135 cc = &slot->s_buf[LU_MAXPATHLEN];
138 if(GET_INFO(dentry->d_sb)->rootlen){
139 if(strncmp(GET_INFO(dentry->d_sb)->root, cc, GET_INFO(dentry->d_sb)->rootlen)){
140 WARN("symlink outside mounted root!");
144 cc += GET_INFO(dentry->d_sb)->rootlen;
147 lu_xlate_symlink(slot->s_buf, slot->s_buf + LU_MAXPATHLEN, slot->s_buf);
155 /* vfs_follow_link somehow manages to call lookup_validate, so we need to
156 release the slot, in case it's the only one, otherwise lu_lookup will
157 fail (avoid a deadlock). bad, bad vfs_follow_link! you break the overall
158 beauty of no kmallocs... */
160 if((tmp = kmalloc(strlen(cc) + 1, GFP_KERNEL)) == NULL){
161 WARN("out of mem!\n");
167 res = vfs_follow_link(nd, tmp);
169 if(tmp != failed_link)
176 struct inode_operations lu_symlink_inode_operations = {
177 .readlink = lu_readlink,
178 .follow_link = lu_followlink,