* better
[mascara-docs.git] / i386 / linux-2.3.21 / fs / ncpfs / symlink.c
blob578b2b9859a9a0e565e49493826b336f72c9a975
1 /*
2 * linux/fs/ncpfs/symlink.c
4 * Code for allowing symbolic links on NCPFS (i.e. NetWare)
5 * Symbolic links are not supported on native NetWare, so we use an
6 * infrequently-used flag (Sh) and store a two-word magic header in
7 * the file to make sure we don't accidentally use a non-link file
8 * as a link.
10 * from linux/fs/ext2/symlink.c
12 * Copyright (C) 1998-99, Frank A. Vorstenbosch
14 * ncpfs symlink handling code
15 * NLS support (c) 1999 Petr Vandrovec
19 #include <linux/config.h>
21 #ifdef CONFIG_NCPFS_EXTRAS
23 #include <asm/uaccess.h>
24 #include <asm/segment.h>
26 #include <linux/errno.h>
27 #include <linux/fs.h>
28 #include <linux/ncp_fs.h>
29 #include <linux/sched.h>
30 #include <linux/mm.h>
31 #include <linux/stat.h>
32 #include "ncplib_kernel.h"
35 /* these magic numbers must appear in the symlink file -- this makes it a bit
36 more resilient against the magic attributes being set on random files. */
38 #define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
39 #define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
41 static int ncp_readlink(struct dentry *, char *, int);
42 static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
43 int ncp_create_new(struct inode *dir, struct dentry *dentry,
44 int mode,int attributes);
47 * symlinks can't do much...
49 struct inode_operations ncp_symlink_inode_operations={
50 NULL, /* no file-operations */
51 NULL, /* create */
52 NULL, /* lookup */
53 NULL, /* link */
54 NULL, /* unlink */
55 NULL, /* symlink */
56 NULL, /* mkdir */
57 NULL, /* rmdir */
58 NULL, /* mknod */
59 NULL, /* rename */
60 ncp_readlink, /* readlink */
61 ncp_follow_link, /* follow_link */
62 NULL, /* get_block */
63 NULL, /* readpage */
64 NULL, /* writepage */
65 NULL, /* flushpage */
66 NULL, /* truncate */
67 NULL, /* permission */
68 NULL, /* smap */
69 NULL /* revalidate */
72 /* ----- follow a symbolic link ------------------------------------------ */
74 static struct dentry *ncp_follow_link(struct dentry *dentry,
75 struct dentry *base,
76 unsigned int follow)
78 struct inode *inode=dentry->d_inode;
79 int error, length, cnt;
80 char *link;
82 #ifdef DEBUG
83 printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
84 #endif
86 if(!S_ISLNK(inode->i_mode)) {
87 dput(base);
88 return ERR_PTR(-EINVAL);
91 if(ncp_make_open(inode,O_RDONLY)) {
92 dput(base);
93 return ERR_PTR(-EIO);
96 for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
97 if (cnt > 10) {
98 dput(base);
99 return ERR_PTR(-EAGAIN); /* -ENOMEM? */
101 schedule();
104 error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
105 0,NCP_MAX_SYMLINK_SIZE,link,&length);
107 if (error!=0 || length<NCP_MIN_SYMLINK_SIZE ||
108 ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
109 dput(base);
110 kfree(link);
111 return ERR_PTR(-EIO);
114 link[length]=0;
116 vol2io(NCP_SERVER(inode), link+8, 0);
118 /* UPDATE_ATIME(inode); */
119 base=lookup_dentry(link+8, base, follow);
120 kfree(link);
122 return base;
125 /* ----- read symbolic link ---------------------------------------------- */
127 static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
129 struct inode *inode=dentry->d_inode;
130 char *link;
131 int length,error;
133 #ifdef DEBUG
134 printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
135 #endif
137 if(!S_ISLNK(inode->i_mode))
138 return -EINVAL;
140 if(ncp_make_open(inode,O_RDONLY))
141 return -EIO;
143 if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL)
144 return -ENOMEM;
146 error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
147 0,NCP_MAX_SYMLINK_SIZE,link,&length);
149 if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
150 ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
151 error = -EIO;
152 goto out;
155 link[length] = 0;
157 vol2io(NCP_SERVER(inode), link+8, 0);
159 error = length - 8;
160 if(copy_to_user(buffer, link+8, error))
161 error = -EFAULT;
163 out:;
164 kfree(link);
165 return error;
168 /* ----- create a new symbolic link -------------------------------------- */
170 int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
171 int i,length;
172 struct inode *inode;
173 char *link;
175 #ifdef DEBUG
176 printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
177 #endif
179 if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
180 return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */
182 if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE)
183 return -EINVAL;
185 if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
186 return -ENOMEM;
188 if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) {
189 kfree(link);
190 return -EIO;
193 inode=dentry->d_inode;
195 ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
196 ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
197 memcpy(link+8, symname, length+1); /* including last zero for io2vol */
199 /* map to/from server charset, do not touch upper/lower case as
200 symlink can point out of ncp filesystem */
201 io2vol(NCP_SERVER(inode), link+8, 0);
203 if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
204 0, length+8, link, &i) || i!=length+8) {
205 kfree(link);
206 return -EIO;
209 kfree(link);
210 return 0;
212 #endif
214 /* ----- EOF ----- */