summaryrefslogtreecommitdiffstats
path: root/fs/isofs/symlink.c
blob: e5a7a2c726d749ddfec7b6c922be4b2b1f583002 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
 *  linux/fs/isofs/symlink.c
 *
 *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  isofs symlink handling code.  This is only used with the Rock Ridge
 *  extensions to iso9660
 */

#include <linux/string.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/iso_fs.h>
#include <linux/stat.h>
#include <linux/malloc.h>

#include <asm/uaccess.h>

static int isofs_readlink(struct dentry *, char *, int);
static struct dentry * isofs_follow_link(struct dentry *, struct dentry *, unsigned int);

/*
 * symlinks can't do much...
 */
struct inode_operations isofs_symlink_inode_operations = {
	NULL,			/* no file-operations */
	NULL,			/* create */
	NULL,			/* lookup */
	NULL,			/* link */
	NULL,			/* unlink */
	NULL,			/* symlink */
	NULL,			/* mkdir */
	NULL,			/* rmdir */
	NULL,			/* mknod */
	NULL,			/* rename */
	isofs_readlink,		/* readlink */
	isofs_follow_link,	/* follow_link */
	NULL,			/* get_block */
	NULL,			/* readpage */
	NULL,			/* writepage */
	NULL,			/* flushpage */
	NULL,			/* truncate */
	NULL,			/* permission */
	NULL,			/* smap */
	NULL			/* revalidate */
};

static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
        char * pnt;
	int i;

	if (buflen > 1023)
		buflen = 1023;
	pnt = get_rock_ridge_symlink(dentry->d_inode);

	if (!pnt)
		return 0;

	i = strlen(pnt);
	if (i > buflen)
		i = buflen; 
	if (copy_to_user(buffer, pnt, i))
		i = -EFAULT; 	
	kfree(pnt);
	return i;
}

static struct dentry * isofs_follow_link(struct dentry * dentry,
					struct dentry *base,
					unsigned int follow)
{
	char * pnt;

	pnt = get_rock_ridge_symlink(dentry->d_inode);
	if(!pnt) {
		dput(base);
		return ERR_PTR(-ELOOP);
	}

	base = lookup_dentry(pnt, base, follow);

	kfree(pnt);
	return base;
}