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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [qnx4/] [namei.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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