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
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>
28 #include <linux/ncp_fs.h>
29 #include <linux/sched.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 */
60 ncp_readlink
, /* readlink */
61 ncp_follow_link
, /* follow_link */
67 NULL
, /* permission */
72 /* ----- follow a symbolic link ------------------------------------------ */
74 static struct dentry
*ncp_follow_link(struct dentry
*dentry
,
78 struct inode
*inode
=dentry
->d_inode
;
79 int error
, length
, cnt
;
83 printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry
,base
,follow
);
86 if(!S_ISLNK(inode
->i_mode
)) {
88 return ERR_PTR(-EINVAL
);
91 if(ncp_make_open(inode
,O_RDONLY
)) {
96 for (cnt
= 0; (link
=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE
+1, GFP_NFS
))==NULL
; cnt
++) {
99 return ERR_PTR(-EAGAIN
); /* -ENOMEM? */
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
) {
111 return ERR_PTR(-EIO
);
116 vol2io(NCP_SERVER(inode
), link
+8, 0);
118 /* UPDATE_ATIME(inode); */
119 base
=lookup_dentry(link
+8, base
, follow
);
125 /* ----- read symbolic link ---------------------------------------------- */
127 static int ncp_readlink(struct dentry
* dentry
, char * buffer
, int buflen
)
129 struct inode
*inode
=dentry
->d_inode
;
134 printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry
,buffer
,buflen
);
137 if(!S_ISLNK(inode
->i_mode
))
140 if(ncp_make_open(inode
,O_RDONLY
))
143 if((link
=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE
+1,GFP_NFS
))==NULL
)
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
) {
157 vol2io(NCP_SERVER(inode
), link
+8, 0);
160 if(copy_to_user(buffer
, link
+8, error
))
168 /* ----- create a new symbolic link -------------------------------------- */
170 int ncp_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
) {
176 printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir
,dentry
,symname
);
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
)
185 if ((link
=(char *)kmalloc(length
+9,GFP_NFS
))==NULL
)
188 if (ncp_create_new(dir
,dentry
,0,aSHARED
|aHIDDEN
)) {
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) {
214 /* ----- EOF ----- */