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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [jffs2/] [current/] [src/] [dir-ecos.c] - Blame information for rev 838

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

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001-2003 Free Software Foundation, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7
 *
8
 * For licensing information, see the file 'LICENCE' in this directory.
9
 *
10
 * $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $
11
 *
12
 */
13
 
14
#include <linux/kernel.h>
15
#include <linux/crc32.h>
16
#include "nodelist.h"
17
 
18
/***********************************************************************/
19
 
20
/* Takes length argument because it can be either NUL-terminated or '/'-terminated */
21
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
22
{
23
        struct jffs2_inode_info *dir_f;
24
        struct jffs2_sb_info *c;
25
        struct jffs2_full_dirent *fd = NULL, *fd_list;
26
        uint32_t ino = 0;
27
        uint32_t hash = full_name_hash(d_name, namelen);
28
        struct _inode *inode = NULL;
29
 
30
        D1(printk("jffs2_lookup()\n"));
31
 
32
        dir_f = JFFS2_INODE_INFO(dir_i);
33
        c = JFFS2_SB_INFO(dir_i->i_sb);
34
 
35
        down(&dir_f->sem);
36
 
37
        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
38
        for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
39
                if (fd_list->nhash == hash &&
40
                    (!fd || fd_list->version > fd->version) &&
41
                    strlen((char *)fd_list->name) == namelen &&
42
                    !strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
43
                        fd = fd_list;
44
                }
45
        }
46
        if (fd)
47
                ino = fd->ino;
48
        up(&dir_f->sem);
49
        if (ino) {
50
                inode = jffs2_iget(dir_i->i_sb, ino);
51
                if (IS_ERR(inode)) {
52
                        printk("jffs2_iget() failed for ino #%u\n", ino);
53
                        return inode;
54
                }
55
        }
56
 
57
        return inode;
58
}
59
 
60
/***********************************************************************/
61
 
62
 
63
 
64
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
65
                 struct _inode **new_i)
66
{
67
        struct jffs2_raw_inode *ri;
68
        struct jffs2_inode_info *f, *dir_f;
69
        struct jffs2_sb_info *c;
70
        struct _inode *inode;
71
        int ret;
72
 
73
        ri = jffs2_alloc_raw_inode();
74
        if (!ri)
75
                return -ENOMEM;
76
 
77
        c = JFFS2_SB_INFO(dir_i->i_sb);
78
 
79
        D1(printk(KERN_DEBUG "jffs2_create()\n"));
80
 
81
        inode = jffs2_new_inode(dir_i, mode, ri);
82
 
83
        if (IS_ERR(inode)) {
84
                D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
85
                jffs2_free_raw_inode(ri);
86
                return PTR_ERR(inode);
87
        }
88
 
89
        f = JFFS2_INODE_INFO(inode);
90
        dir_f = JFFS2_INODE_INFO(dir_i);
91
 
92
        ret = jffs2_do_create(c, dir_f, f, ri,
93
                              (const char *)d_name,
94
                              strlen((char *)d_name));
95
 
96
        if (ret) {
97
                inode->i_nlink = 0;
98
                jffs2_iput(inode);
99
                jffs2_free_raw_inode(ri);
100
                return ret;
101
        }
102
 
103
        jffs2_free_raw_inode(ri);
104
 
105
        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
106
                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
107
        *new_i = inode;
108
        return 0;
109
}
110
 
111
/***********************************************************************/
112
 
113
 
114
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
115
{
116
        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
117
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
118
        struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
119
        int ret;
120
 
121
        ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
122
                               strlen((char *)d_name), dead_f);
123
        if (dead_f->inocache)
124
                d_inode->i_nlink = dead_f->inocache->nlink;
125
        return ret;
126
}
127
/***********************************************************************/
128
 
129
 
130
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
131
{
132
        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
133
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
134
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
135
        int ret;
136
 
137
        /* XXX: This is ugly */
138
        uint8_t type = (old_d_inode->i_mode & S_IFMT) >> 12;
139
        if (!type) type = DT_REG;
140
 
141
        ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
142
                            (const char * )d_name,
143
                            strlen((char *)d_name));
144
 
145
        if (!ret) {
146
                down(&f->sem);
147
                old_d_inode->i_nlink = ++f->inocache->nlink;
148
                up(&f->sem);
149
        }
150
        return ret;
151
}
152
 
153
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
154
{
155
        struct jffs2_inode_info *f, *dir_f;
156
        struct jffs2_sb_info *c;
157
        struct _inode *inode;
158
        struct jffs2_raw_inode *ri;
159
        struct jffs2_raw_dirent *rd;
160
        struct jffs2_full_dnode *fn;
161
        struct jffs2_full_dirent *fd;
162
        int namelen;
163
        uint32_t alloclen, phys_ofs;
164
        int ret;
165
 
166
        mode |= S_IFDIR;
167
 
168
        ri = jffs2_alloc_raw_inode();
169
        if (!ri)
170
                return -ENOMEM;
171
 
172
        c = JFFS2_SB_INFO(dir_i->i_sb);
173
 
174
        /* Try to reserve enough space for both node and dirent.
175
         * Just the node will do for now, though
176
         */
177
        namelen = strlen((char *)d_name);
178
        ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
179
 
180
        if (ret) {
181
                jffs2_free_raw_inode(ri);
182
                return ret;
183
        }
184
 
185
        inode = jffs2_new_inode(dir_i, mode, ri);
186
 
187
        if (IS_ERR(inode)) {
188
                jffs2_free_raw_inode(ri);
189
                jffs2_complete_reservation(c);
190
                return PTR_ERR(inode);
191
        }
192
 
193
        f = JFFS2_INODE_INFO(inode);
194
 
195
        ri->data_crc = cpu_to_je32(0);
196
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
197
 
198
        fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
199
 
200
        jffs2_free_raw_inode(ri);
201
 
202
        if (IS_ERR(fn)) {
203
                /* Eeek. Wave bye bye */
204
                up(&f->sem);
205
                jffs2_complete_reservation(c);
206
                inode->i_nlink = 0;
207
                jffs2_iput(inode);
208
                return PTR_ERR(fn);
209
        }
210
        /* No data here. Only a metadata node, which will be
211
           obsoleted by the first data write
212
        */
213
        f->metadata = fn;
214
        up(&f->sem);
215
 
216
        jffs2_complete_reservation(c);
217
        ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
218
        if (ret) {
219
                /* Eep. */
220
                inode->i_nlink = 0;
221
                jffs2_iput(inode);
222
                return ret;
223
        }
224
 
225
        rd = jffs2_alloc_raw_dirent();
226
        if (!rd) {
227
                /* Argh. Now we treat it like a normal delete */
228
                jffs2_complete_reservation(c);
229
                inode->i_nlink = 0;
230
                jffs2_iput(inode);
231
                return -ENOMEM;
232
        }
233
 
234
        dir_f = JFFS2_INODE_INFO(dir_i);
235
        down(&dir_f->sem);
236
 
237
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
238
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
239
        rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
240
        rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
241
 
242
        rd->pino = cpu_to_je32(dir_i->i_ino);
243
        rd->version = cpu_to_je32(++dir_f->highest_version);
244
        rd->ino = cpu_to_je32(inode->i_ino);
245
        rd->mctime = cpu_to_je32(cyg_timestamp());
246
        rd->nsize = namelen;
247
        rd->type = DT_DIR;
248
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
249
        rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));
250
 
251
        fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
252
 
253
        jffs2_complete_reservation(c);
254
        jffs2_free_raw_dirent(rd);
255
 
256
        if (IS_ERR(fd)) {
257
                /* dirent failed to write. Delete the inode normally
258
                   as if it were the final unlink() */
259
                up(&dir_f->sem);
260
                inode->i_nlink = 0;
261
                jffs2_iput(inode);
262
                return PTR_ERR(fd);
263
        }
264
 
265
        /* Link the fd into the inode's list, obsoleting an old
266
           one if necessary. */
267
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
268
        up(&dir_f->sem);
269
 
270
        jffs2_iput(inode);
271
        return 0;
272
}
273
 
274
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
275
{
276
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
277
        struct jffs2_full_dirent *fd;
278
 
279
        for (fd = f->dents ; fd; fd = fd->next) {
280
                if (fd->ino)
281
                        return EPERM; //-ENOTEMPTY;
282
        }
283
        return jffs2_unlink(dir_i, d_inode, d_name);
284
}
285
 
286
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
287
                  struct _inode *new_dir_i, const unsigned char *new_d_name)
288
{
289
        int ret;
290
        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
291
        struct jffs2_inode_info *victim_f = NULL;
292
        uint8_t type;
293
 
294
#if 0 /* FIXME -- this really doesn't belong in individual file systems. 
295
         The fileio code ought to do this for us, or at least part of it */
296
        if (new_dentry->d_inode) {
297
                if (S_ISDIR(d_inode->i_mode) &&
298
                    !S_ISDIR(new_dentry->d_inode->i_mode)) {
299
                        /* Cannot rename directory over non-directory */
300
                        return -EINVAL;
301
                }
302
 
303
                victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
304
 
305
                if (S_ISDIR(new_dentry->d_inode->i_mode)) {
306
                        struct jffs2_full_dirent *fd;
307
 
308
                        if (!S_ISDIR(d_inode->i_mode)) {
309
                                /* Cannot rename non-directory over directory */
310
                                return -EINVAL;
311
                        }
312
                        down(&victim_f->sem);
313
                        for (fd = victim_f->dents; fd; fd = fd->next) {
314
                                if (fd->ino) {
315
                                        up(&victim_f->sem);
316
                                        return -ENOTEMPTY;
317
                                }
318
                        }
319
                        up(&victim_f->sem);
320
                }
321
        }
322
#endif
323
 
324
        /* XXX: We probably ought to alloc enough space for
325
           both nodes at the same time. Writing the new link,
326
           then getting -ENOSPC, is quite bad :)
327
        */
328
 
329
        /* Make a hard link */
330
 
331
        /* XXX: This is ugly */
332
        type = (d_inode->i_mode & S_IFMT) >> 12;
333
        if (!type) type = DT_REG;
334
 
335
        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
336
                            d_inode->i_ino, type,
337
                            (const char *)new_d_name,
338
                            strlen((char *)new_d_name));
339
 
340
        if (ret)
341
                return ret;
342
 
343
        if (victim_f) {
344
                /* There was a victim. Kill it off nicely */
345
                /* Don't oops if the victim was a dirent pointing to an
346
                   inode which didn't exist. */
347
                if (victim_f->inocache) {
348
                        down(&victim_f->sem);
349
                        victim_f->inocache->nlink--;
350
                        up(&victim_f->sem);
351
                }
352
        }
353
 
354
        /* Unlink the original */
355
        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
356
                              (const char *)old_d_name,
357
                              strlen((char *)old_d_name), NULL);
358
 
359
        if (ret) {
360
                /* Oh shit. We really ought to make a single node which can do both atomically */
361
                struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
362
                down(&f->sem);
363
                if (f->inocache)
364
                        d_inode->i_nlink = f->inocache->nlink++;
365
                up(&f->sem);
366
 
367
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
368
        }
369
        return ret;
370
}
371
 

powered by: WebSVN 2.1.0

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