|
|
1.1 root 1: /*
2: * linux/fs/ext/symlink.c
3: *
1.1.1.2 ! root 4: * Copyright (C) 1992 Remy Card ([email protected])
1.1 root 5: *
6: * from
7: *
8: * linux/fs/minix/symlink.c
9: *
1.1.1.2 ! root 10: * Copyright (C) 1991, 1992 Linus Torvalds
1.1 root 11: *
12: * ext symlink handling code
13: */
14:
15: #include <asm/segment.h>
16:
1.1.1.2 ! root 17: #include <linux/errno.h>
1.1 root 18: #include <linux/sched.h>
19: #include <linux/fs.h>
20: #include <linux/ext_fs.h>
21: #include <linux/stat.h>
22:
23: static int ext_readlink(struct inode *, char *, int);
24: static struct inode * ext_follow_link(struct inode *, struct inode *);
25:
26: /*
27: * symlinks can't do much...
28: */
29: struct inode_operations ext_symlink_inode_operations = {
30: NULL, /* no file-operations */
31: NULL, /* create */
32: NULL, /* lookup */
33: NULL, /* link */
34: NULL, /* unlink */
35: NULL, /* symlink */
36: NULL, /* mkdir */
37: NULL, /* rmdir */
38: NULL, /* mknod */
39: NULL, /* rename */
40: ext_readlink, /* readlink */
41: ext_follow_link, /* follow_link */
42: NULL, /* bmap */
43: NULL /* truncate */
44: };
45:
46: static struct inode * ext_follow_link(struct inode * dir, struct inode * inode)
47: {
48: unsigned short fs;
49: struct buffer_head * bh;
50:
51: if (!dir) {
52: dir = current->root;
53: dir->i_count++;
54: }
55: if (!inode) {
56: iput(dir);
57: return NULL;
58: }
59: if (!S_ISLNK(inode->i_mode)) {
60: iput(dir);
61: return inode;
62: }
63: __asm__("mov %%fs,%0":"=r" (fs));
64: if ((current->link_count > 5) || !inode->i_data[0] ||
1.1.1.2 ! root 65: !(bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
1.1 root 66: iput(dir);
67: iput(inode);
68: return NULL;
69: }
70: iput(inode);
71: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
72: current->link_count++;
73: inode = _namei(bh->b_data,dir,1);
74: current->link_count--;
75: __asm__("mov %0,%%fs"::"r" (fs));
76: brelse(bh);
77: return inode;
78: }
79:
80: static int ext_readlink(struct inode * inode, char * buffer, int buflen)
81: {
82: struct buffer_head * bh;
83: int i;
84: char c;
85:
86: if (!S_ISLNK(inode->i_mode)) {
87: iput(inode);
88: return -EINVAL;
89: }
90: if (buflen > 1023)
91: buflen = 1023;
92: if (inode->i_data[0])
1.1.1.2 ! root 93: bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE);
1.1 root 94: else
95: bh = NULL;
96: iput(inode);
97: if (!bh)
98: return 0;
99: i = 0;
100: while (i<buflen && (c = bh->b_data[i])) {
101: i++;
102: put_fs_byte(c,buffer++);
103: }
104: brelse(bh);
105: return i;
106: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.