OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [symlink.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/affs/symlink.c
3
 *
4
 *  1995  Hans-Joachim Widmaier - Modified for affs.
5
 *
6
 *  Copyright (C) 1991, 1992  Linus Torvalds
7
 *
8
 *  affs symlink handling code
9
 */
10
 
11
#include <linux/errno.h>
12
#include <linux/sched.h>
13
#include <linux/malloc.h>
14
#include <linux/fs.h>
15
#include <linux/stat.h>
16
#include <linux/affs_fs.h>
17
#include <linux/amigaffs.h>
18
#include <asm/segment.h>
19
 
20
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
21
 
22
static int affs_readlink(struct inode *, char *, int);
23
static int affs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
24
 
25
struct inode_operations affs_symlink_inode_operations = {
26
        NULL,                   /* no file-operations */
27
        NULL,                   /* create */
28
        NULL,                   /* lookup */
29
        NULL,                   /* link */
30
        NULL,                   /* unlink */
31
        NULL,                   /* symlink */
32
        NULL,                   /* mkdir */
33
        NULL,                   /* rmdir */
34
        NULL,                   /* mknod */
35
        NULL,                   /* rename */
36
        affs_readlink,          /* readlink */
37
        affs_follow_link,       /* follow_link */
38
        NULL,                   /* bmap */
39
        NULL,                   /* truncate */
40
        NULL                    /* permission */
41
};
42
 
43
static int
44
affs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode,
45
                 struct inode **res_inode)
46
{
47
        struct buffer_head      *bh;
48
        struct slink_front      *lf;
49
        char                    *buffer;
50
        int                      error;
51
        int                      i, j;
52
        char                     c;
53
        char                     lc;
54
 
55
        pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
56
 
57
        *res_inode = NULL;
58
        if (!dir) {
59
                dir = current->fs->root;
60
                dir->i_count++;
61
        }
62
        if (!inode) {
63
                iput(dir);
64
                return -ENOENT;
65
        }
66
        if (!S_ISLNK(inode->i_mode)) {
67
                iput(dir);
68
                *res_inode = inode;
69
                return 0;
70
        }
71
        if (current->link_count > 5) {
72
                iput(inode);
73
                iput(dir);
74
                return -ELOOP;
75
        }
76
        if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
77
                iput(inode);
78
                iput(dir);
79
                return -ENOSPC;
80
        }
81
        bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
82
        i  = 0;
83
        j  = 0;
84
        if (!bh) {
85
                printk("AFFS: unable to read i-node block %lu\n",inode->i_ino);
86
                kfree(buffer);
87
                iput(inode);
88
                iput(dir);
89
                return -EIO;
90
        }
91
        lf = (struct slink_front *)bh->b_data;
92
        lc = 0;
93
        if (strchr(lf->symname,':')) {          /* Handle assign or volume name */
94
                while (i < 1023 && (c = inode->i_sb->u.affs_sb.s_prefix[i]))
95
                        buffer[i++] = c;
96
                while (i < 1023 && lf->symname[j] != ':')
97
                        buffer[i++] = lf->symname[j++];
98
                if (i < 1023)
99
                         buffer[i++] = '/';
100
                j++;
101
                lc = '/';
102
        }
103
        while (i < 1023 && (c = lf->symname[j])) {
104
                if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
105
                        buffer[i++] = '.';
106
                        buffer[i++] = '.';
107
                }
108
                buffer[i++] = c;
109
                lc = c;
110
                j++;
111
        }
112
        buffer[i] = '\0';
113
        affs_brelse(bh);
114
        iput(inode);
115
        current->link_count++;
116
        error = open_namei(buffer,flag,mode,res_inode,dir);
117
        current->link_count--;
118
        kfree(buffer);
119
        return error;
120
}
121
 
122
static int
123
affs_readlink(struct inode *inode, char *buffer, int buflen)
124
{
125
        struct buffer_head      *bh;
126
        struct slink_front      *lf;
127
        int                      i, j;
128
        char                     c;
129
        char                     lc;
130
 
131
        pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
132
 
133
        if (!S_ISLNK(inode->i_mode)) {
134
                iput(inode);
135
                return -EINVAL;
136
        }
137
        bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
138
        i  = 0;
139
        j  = 0;
140
        if (!bh) {
141
                printk("AFFS: unable to read i-node block %lu\n",inode->i_ino);
142
                goto symlink_end;
143
        }
144
        lf = (struct slink_front *)bh->b_data;
145
        lc = 0;
146
 
147
        if (strchr(lf->symname,':')) {          /* Handle assign or volume name */
148
                while (i < buflen && (c = inode->i_sb->u.affs_sb.s_prefix[i])) {
149
                        put_user(c,buffer++);
150
                        i++;
151
                }
152
                while (i < buflen && (c = lf->symname[j]) != ':') {
153
                        put_user(c,buffer++);
154
                        i++, j++;
155
                }
156
                if (i < buflen) {
157
                        put_user('/',buffer++);
158
                        i++, j++;
159
                }
160
                lc = '/';
161
        }
162
        while (i < buflen && (c = lf->symname[j])) {
163
                if (c == '/' && lc == '/' && (i + 3 < buflen)) {        /* parent dir */
164
                        put_user('.',buffer++);
165
                        put_user('.',buffer++);
166
                        i += 2;
167
                }
168
                put_user(c,buffer++);
169
                lc = c;
170
                i++, j++;
171
        }
172
symlink_end:
173
        iput(inode);
174
        affs_brelse(bh);
175
        return i;
176
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.