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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [qnx4/] [namei.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * QNX4 file system, Linux implementation.
3
 *
4
 * Version : 0.2.1
5
 *
6
 * Using parts of the xiafs filesystem.
7
 *
8
 * History :
9
 *
10
 * 01-06-1998 by Richard Frowijn : first release.
11
 * 21-06-1998 by Frank Denis : dcache support, fixed error codes.
12
 * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
13
 */
14
 
15
#include <linux/config.h>
16
#include <linux/sched.h>
17
#include <linux/qnx4_fs.h>
18
#include <linux/kernel.h>
19
#include <linux/string.h>
20
#include <linux/stat.h>
21
#include <linux/fcntl.h>
22
#include <linux/errno.h>
23
 
24
#include <asm/segment.h>
25
 
26
/*
27
 * check if the filename is correct. For some obscure reason, qnx writes a
28
 * new file twice in the directory entry, first with all possible options at 0
29
 * and for a second time the way it is, they want us not to access the qnx
30
 * filesystem when whe are using linux.
31
 */
32
static int qnx4_match(int len, const char *name,
33
                      struct buffer_head *bh, unsigned long *offset)
34
{
35
        struct qnx4_inode_entry *de;
36
        int namelen, thislen;
37
 
38
        if (bh == NULL) {
39
                printk("qnx4: matching unassigned buffer !\n");
40
                return 0;
41
        }
42
        de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
43
        *offset += QNX4_DIR_ENTRY_SIZE;
44
        if ((de->di_status & QNX4_FILE_LINK) != 0) {
45
                namelen = QNX4_NAME_MAX;
46
        } else {
47
                namelen = QNX4_SHORT_NAME_MAX;
48
        }
49
        /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
50
        if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
51
                return 1;
52
        }
53
        thislen = strlen( de->di_fname );
54
        if ( thislen > namelen )
55
                thislen = namelen;
56
        if (len != thislen) {
57
                return 0;
58
        }
59
        if (strncmp(name, de->di_fname, len) == 0) {
60
                if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
61
                        return 1;
62
                }
63
        }
64
        return 0;
65
}
66
 
67
static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
68
           const char *name, struct qnx4_inode_entry **res_dir, int *ino)
69
{
70
        unsigned long block, offset, blkofs;
71
        struct buffer_head *bh;
72
 
73
        *res_dir = NULL;
74
        if (!dir->i_sb) {
75
                printk("qnx4: no superblock on dir.\n");
76
                return NULL;
77
        }
78
        bh = NULL;
79
        block = offset = blkofs = 0;
80
        while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
81
                if (!bh) {
82
                        bh = qnx4_bread(dir, blkofs, 0);
83
                        if (!bh) {
84
                                blkofs++;
85
                                continue;
86
                        }
87
                }
88
                *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
89
                if (qnx4_match(len, name, bh, &offset)) {
90
                        block = qnx4_block_map( dir, blkofs );
91
                        *ino = block * QNX4_INODES_PER_BLOCK +
92
                            (offset / QNX4_DIR_ENTRY_SIZE) - 1;
93
                        return bh;
94
                }
95
                if (offset < bh->b_size) {
96
                        continue;
97
                }
98
                brelse(bh);
99
                bh = NULL;
100
                offset = 0;
101
                blkofs++;
102
        }
103
        brelse(bh);
104
        *res_dir = NULL;
105
        return NULL;
106
}
107
 
108
struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry)
109
{
110
        int ino;
111
        struct qnx4_inode_entry *de;
112
        struct qnx4_link_info *lnk;
113
        struct buffer_head *bh;
114
        const char *name = dentry->d_name.name;
115
        int len = dentry->d_name.len;
116
        struct inode *foundinode = NULL;
117
 
118
        if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
119
                goto out;
120
        /* The entry is linked, let's get the real info */
121
        if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) {
122
                lnk = (struct qnx4_link_info *) de;
123
                ino = (le32_to_cpu(lnk->dl_inode_blk) - 1) *
124
                    QNX4_INODES_PER_BLOCK +
125
                    lnk->dl_inode_ndx;
126
        }
127
        brelse(bh);
128
 
129
        if ((foundinode = iget(dir->i_sb, ino)) == NULL) {
130
                QNX4DEBUG(("qnx4: lookup->iget -> NULL\n"));
131
                return ERR_PTR(-EACCES);
132
        }
133
out:
134
        d_add(dentry, foundinode);
135
 
136
        return NULL;
137
}
138
 
139
#ifdef CONFIG_QNX4FS_RW
140
int qnx4_create(struct inode *dir, struct dentry *dentry, int mode)
141
{
142
        QNX4DEBUG(("qnx4: qnx4_create\n"));
143
        if (dir == NULL) {
144
                return -ENOENT;
145
        }
146
        return -ENOSPC;
147
}
148
 
149
int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
150
{
151
        struct buffer_head *bh;
152
        struct qnx4_inode_entry *de;
153
        struct inode *inode;
154
        int retval;
155
        int ino;
156
 
157
        QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
158
        bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
159
                             &de, &ino);
160
        if (bh == NULL) {
161
                return -ENOENT;
162
        }
163
        inode = dentry->d_inode;
164
        if (inode->i_ino != ino) {
165
                retval = -EIO;
166
                goto end_rmdir;
167
        }
168
#if 0
169
        if (!empty_dir(inode)) {
170
                retval = -ENOTEMPTY;
171
                goto end_rmdir;
172
        }
173
#endif
174
        if (inode->i_nlink != 2) {
175
                QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
176
        }
177
        QNX4DEBUG(("qnx4: deleting directory\n"));
178
        de->di_status = 0;
179
        memset(de->di_fname, 0, sizeof de->di_fname);
180
        de->di_mode = 0;
181
        mark_buffer_dirty(bh);
182
        inode->i_nlink = 0;
183
        mark_inode_dirty(inode);
184
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
185
        dir->i_nlink--;
186
        mark_inode_dirty(dir);
187
        retval = 0;
188
 
189
      end_rmdir:
190
        brelse(bh);
191
 
192
        return retval;
193
}
194
 
195
int qnx4_unlink(struct inode *dir, struct dentry *dentry)
196
{
197
        struct buffer_head *bh;
198
        struct qnx4_inode_entry *de;
199
        struct inode *inode;
200
        int retval;
201
        int ino;
202
 
203
        QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name));
204
        bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
205
                             &de, &ino);
206
        if (bh == NULL) {
207
                return -ENOENT;
208
        }
209
        inode = dentry->d_inode;
210
        if (inode->i_ino != ino) {
211
                retval = -EIO;
212
                goto end_unlink;
213
        }
214
        retval = -EPERM;
215
        if (!inode->i_nlink) {
216
                QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
217
                           kdevname(inode->i_dev),
218
                           inode->i_ino, inode->i_nlink));
219
                inode->i_nlink = 1;
220
        }
221
        de->di_status = 0;
222
        memset(de->di_fname, 0, sizeof de->di_fname);
223
        de->di_mode = 0;
224
        mark_buffer_dirty(bh);
225
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
226
        mark_inode_dirty(dir);
227
        inode->i_nlink--;
228
        inode->i_ctime = dir->i_ctime;
229
        mark_inode_dirty(inode);
230
        retval = 0;
231
 
232
      end_unlink:
233
        brelse(bh);
234
 
235
        return retval;
236
}
237
#endif

powered by: WebSVN 2.1.0

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