4 * Copyright (c) 1999 Al Smith
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
9 #include <linux/string.h>
10 #include <linux/malloc.h>
11 #include <linux/efs_fs.h>
13 static int efs_readlink(struct dentry
*, char *, int);
14 static struct dentry
* efs_follow_link(struct dentry
*, struct dentry
*, unsigned int);
16 struct inode_operations efs_symlink_inode_operations
= {
17 NULL
, /* no symlink file-operations */
27 efs_readlink
, /* readlink */
28 efs_follow_link
, /* follow_link */
34 NULL
, /* permission */
39 static char *efs_linktarget(struct inode
*in
, int *len
) {
41 struct buffer_head
* bh
;
42 efs_block_t size
= in
->i_size
;
44 if (size
> 2 * EFS_BLOCKSIZE
) {
45 printk(KERN_ERR
"EFS: linktarget(): name too long: %lu\n", in
->i_size
);
49 if (!(name
= kmalloc(size
+ 1, GFP_KERNEL
)))
52 /* read first 512 bytes of link target */
53 bh
= bread(in
->i_dev
, efs_bmap(in
, 0), EFS_BLOCKSIZE
);
56 printk(KERN_ERR
"EFS: linktarget(): couldn't read block %d\n", efs_bmap(in
, 0));
60 memcpy(name
, bh
->b_data
, (size
> EFS_BLOCKSIZE
) ? EFS_BLOCKSIZE
: size
);
63 if (size
> EFS_BLOCKSIZE
) {
64 bh
= bread(in
->i_dev
, efs_bmap(in
, 1), EFS_BLOCKSIZE
);
67 printk(KERN_ERR
"EFS: linktarget(): couldn't read block %d\n", efs_bmap(in
, 1));
70 memcpy(name
+ EFS_BLOCKSIZE
, bh
->b_data
, size
- EFS_BLOCKSIZE
);
74 name
[size
] = (char) 0;
80 static struct dentry
*efs_follow_link(struct dentry
*dentry
, struct dentry
*base
, unsigned int follow
) {
82 struct inode
*inode
= dentry
->d_inode
;
84 if (!(name
= efs_linktarget(inode
, NULL
))) {
86 return ERR_PTR(-ELOOP
);
88 base
= lookup_dentry(name
, base
, follow
);
94 static int efs_readlink(struct dentry
* dir
, char * buf
, int bufsiz
) {
97 struct inode
*inode
= dir
->d_inode
;
99 if (!(name
= efs_linktarget(inode
, &bufsiz
))) return 0;
100 rc
= copy_to_user(buf
, name
, bufsiz
) ? -EFAULT
: bufsiz
;