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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ext2/] [namei.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/ext2/namei.c
3
 *
4
 * Copyright (C) 1992, 1993, 1994, 1995
5
 * Remy Card (card@masi.ibp.fr)
6
 * Laboratoire MASI - Institut Blaise Pascal
7
 * Universite Pierre et Marie Curie (Paris VI)
8
 *
9
 *  from
10
 *
11
 *  linux/fs/minix/namei.c
12
 *
13
 *  Copyright (C) 1991, 1992  Linus Torvalds
14
 *
15
 *  Big-endian to little-endian byte-swapping/bitmaps by
16
 *        David S. Miller (davem@caip.rutgers.edu), 1995
17
 *
18
 */
19
 
20
#include <asm/segment.h>
21
 
22
#include <linux/errno.h>
23
#include <linux/fs.h>
24
#include <linux/ext2_fs.h>
25
#include <linux/fcntl.h>
26
#include <linux/sched.h>
27
#include <linux/stat.h>
28
#include <linux/string.h>
29
#include <linux/locks.h>
30
 
31
/*
32
 * define how far ahead to read directories while searching them.
33
 */
34
#define NAMEI_RA_CHUNKS  2
35
#define NAMEI_RA_BLOCKS  4
36
#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
37
#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
38
 
39
/*
40
 * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
41
 */
42
static int ext2_match (int len, const char * const name,
43
                       struct ext2_dir_entry * de)
44
{
45
        if (!de || !swab32(de->inode) || len > EXT2_NAME_LEN)
46
                return 0;
47
        /*
48
         * "" means "." ---> so paths like "/usr/lib//libc.a" work
49
         */
50
        if (!len && swab16(de->name_len) == 1 && (de->name[0] == '.') &&
51
           (de->name[1] == '\0'))
52
                return 1;
53
        if (len != swab16(de->name_len))
54
                return 0;
55
        return !memcmp(name, de->name, len);
56
}
57
 
58
/*
59
 *      ext2_find_entry()
60
 *
61
 * finds an entry in the specified directory with the wanted name. It
62
 * returns the cache buffer in which the entry was found, and the entry
63
 * itself (as a parameter - res_dir). It does NOT read the inode of the
64
 * entry - you'll have to do that yourself if you want to.
65
 */
66
static struct buffer_head * ext2_find_entry (struct inode * dir,
67
                                             const char * const name, int namelen,
68
                                             struct ext2_dir_entry ** res_dir)
69
{
70
        struct super_block * sb;
71
        struct buffer_head * bh_use[NAMEI_RA_SIZE];
72
        struct buffer_head * bh_read[NAMEI_RA_SIZE];
73
        unsigned long offset;
74
        int block, toread, i, err;
75
 
76
        *res_dir = NULL;
77
        if (!dir)
78
                return NULL;
79
        sb = dir->i_sb;
80
 
81
        if (namelen > EXT2_NAME_LEN)
82
                return NULL;
83
 
84
        memset (bh_use, 0, sizeof (bh_use));
85
        toread = 0;
86
        for (block = 0; block < NAMEI_RA_SIZE; ++block) {
87
                struct buffer_head * bh;
88
 
89
                if ((block << EXT2_BLOCK_SIZE_BITS (sb)) >= dir->i_size)
90
                        break;
91
                bh = ext2_getblk (dir, block, 0, &err);
92
                bh_use[block] = bh;
93
                if (bh && !buffer_uptodate(bh))
94
                        bh_read[toread++] = bh;
95
        }
96
 
97
        for (block = 0, offset = 0; offset < dir->i_size; block++) {
98
                struct buffer_head * bh;
99
                struct ext2_dir_entry * de;
100
                char * dlimit;
101
 
102
                if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
103
                        ll_rw_block (READ, toread, bh_read);
104
                        toread = 0;
105
                }
106
                bh = bh_use[block % NAMEI_RA_SIZE];
107
 
108
                if (!bh) {
109
                        ext2_error (sb, "ext2_find_entry",
110
                                    "directory #%lu contains a hole at offset %lu",
111
                                    dir->i_ino, offset);
112
                        offset += sb->s_blocksize;
113
                        continue;
114
                }
115
                wait_on_buffer (bh);
116
                if (!buffer_uptodate(bh)) {
117
                        /*
118
                         * read error: all bets are off
119
                         */
120
                        break;
121
                }
122
 
123
                de = (struct ext2_dir_entry *) bh->b_data;
124
                dlimit = bh->b_data + sb->s_blocksize;
125
                while ((char *) de < dlimit) {
126
                        if (!ext2_check_dir_entry ("ext2_find_entry", dir,
127
                                                   de, bh, offset))
128
                                goto failure;
129
                        if (swab32(de->inode) != 0 && ext2_match (namelen, name, de)) {
130
                                for (i = 0; i < NAMEI_RA_SIZE; ++i) {
131
                                        if (bh_use[i] != bh)
132
                                                brelse (bh_use[i]);
133
                                }
134
                                *res_dir = de;
135
                                return bh;
136
                        }
137
                        offset += swab16(de->rec_len);
138
                        de = (struct ext2_dir_entry *)
139
                                ((char *) de + swab16(de->rec_len));
140
                }
141
 
142
                brelse (bh);
143
                if (((block + NAMEI_RA_SIZE) << EXT2_BLOCK_SIZE_BITS (sb)) >=
144
                    dir->i_size)
145
                        bh = NULL;
146
                else
147
                        bh = ext2_getblk (dir, block + NAMEI_RA_SIZE, 0, &err);
148
                bh_use[block % NAMEI_RA_SIZE] = bh;
149
                if (bh && !buffer_uptodate(bh))
150
                        bh_read[toread++] = bh;
151
        }
152
 
153
failure:
154
        for (i = 0; i < NAMEI_RA_SIZE; ++i)
155
                brelse (bh_use[i]);
156
        return NULL;
157
}
158
 
159
int ext2_lookup (struct inode * dir, const char * name, int len,
160
                 struct inode ** result)
161
{
162
        unsigned long ino;
163
        struct ext2_dir_entry * de;
164
        struct buffer_head * bh;
165
 
166
        *result = NULL;
167
        if (!dir)
168
                return -ENOENT;
169
        if (!S_ISDIR(dir->i_mode)) {
170
                iput (dir);
171
                return -ENOTDIR;
172
        }
173
        if (len > EXT2_NAME_LEN) {
174
                iput (dir);
175
                return -ENAMETOOLONG;
176
        }
177
        if (dcache_lookup(dir, name, len, &ino)) {
178
                if (!ino) {
179
                        iput(dir);
180
                        return -ENOENT;
181
                }
182
                if (!(*result = iget (dir->i_sb, ino))) {
183
                        iput (dir);
184
                        return -EACCES;
185
                }
186
                iput (dir);
187
                return 0;
188
        }
189
        ino = dir->i_version;
190
        if (!(bh = ext2_find_entry (dir, name, len, &de))) {
191
                if (ino == dir->i_version)
192
                        dcache_add(dir, name, len, 0);
193
                iput (dir);
194
                return -ENOENT;
195
        }
196
        ino = swab32(de->inode);
197
        dcache_add(dir, name, len, ino);
198
        brelse (bh);
199
        if (!(*result = iget (dir->i_sb, ino))) {
200
                iput (dir);
201
                return -EACCES;
202
        }
203
        iput (dir);
204
        return 0;
205
}
206
 
207
/*
208
 *      ext2_add_entry()
209
 *
210
 * adds a file entry to the specified directory, using the same
211
 * semantics as ext2_find_entry(). It returns NULL if it failed.
212
 *
213
 * NOTE!! The inode part of 'de' is left at 0 - which means you
214
 * may not sleep between calling this and putting something into
215
 * the entry, as someone else might have used it while you slept.
216
 */
217
static struct buffer_head * ext2_add_entry (struct inode * dir,
218
                                            const char * name, int namelen,
219
                                            struct ext2_dir_entry ** res_dir,
220
                                            int *err)
221
{
222
        unsigned long offset;
223
        unsigned short rec_len;
224
        struct buffer_head * bh;
225
        struct ext2_dir_entry * de, * de1;
226
        struct super_block * sb;
227
 
228
        *err = -EINVAL;
229
        *res_dir = NULL;
230
        if (!dir)
231
                return NULL;
232
        sb = dir->i_sb;
233
 
234
        if (namelen > EXT2_NAME_LEN)
235
        {
236
                *err = -ENAMETOOLONG;
237
                return NULL;
238
        }
239
 
240
        if (!namelen)
241
                return NULL;
242
        /*
243
         * Is this a busy deleted directory?  Can't create new files if so
244
         */
245
        if (dir->i_size == 0)
246
        {
247
                *err = -ENOENT;
248
                return NULL;
249
        }
250
        bh = ext2_bread (dir, 0, 0, err);
251
        if (!bh)
252
                return NULL;
253
        rec_len = EXT2_DIR_REC_LEN(namelen);
254
        offset = 0;
255
        de = (struct ext2_dir_entry *) bh->b_data;
256
        *err = -ENOSPC;
257
        while (1) {
258
                if ((char *)de >= sb->s_blocksize + bh->b_data) {
259
                        brelse (bh);
260
                        bh = NULL;
261
                        bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, err);
262
                        if (!bh)
263
                                return NULL;
264
                        if (dir->i_size <= offset) {
265
                                if (dir->i_size == 0) {
266
                                        *err = -ENOENT;
267
                                        return NULL;
268
                                }
269
 
270
                                ext2_debug ("creating next block\n");
271
 
272
                                de = (struct ext2_dir_entry *) bh->b_data;
273
                                de->inode = swab32(0);
274
                                de->rec_len = swab16(sb->s_blocksize);
275
                                dir->i_size = offset + sb->s_blocksize;
276
                                dir->i_dirt = 1;
277
                        } else {
278
 
279
                                ext2_debug ("skipping to next block\n");
280
 
281
                                de = (struct ext2_dir_entry *) bh->b_data;
282
                        }
283
                }
284
                if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
285
                                           offset)) {
286
                        *err = -ENOENT;
287
                        brelse (bh);
288
                        return NULL;
289
                }
290
                if (swab32(de->inode) != 0 && ext2_match (namelen, name, de)) {
291
                                *err = -EEXIST;
292
                                brelse (bh);
293
                                return NULL;
294
                }
295
                if ((swab32(de->inode) == 0 && swab16(de->rec_len) >= rec_len) ||
296
                    (swab16(de->rec_len) >= EXT2_DIR_REC_LEN(swab16(de->name_len)) + rec_len)) {
297
                        offset += swab16(de->rec_len);
298
                        if (swab32(de->inode)) {
299
                                de1 = (struct ext2_dir_entry *) ((char *) de +
300
                                        EXT2_DIR_REC_LEN(swab16(de->name_len)));
301
                                de1->rec_len = swab16(swab16(de->rec_len) -
302
                                        EXT2_DIR_REC_LEN(swab16(de->name_len)));
303
                                de->rec_len = swab16(EXT2_DIR_REC_LEN(swab16(de->name_len)));
304
                                de = de1;
305
                        }
306
                        de->inode = swab32(0);
307
                        de->name_len = swab16(namelen);
308
                        memcpy (de->name, name, namelen);
309
                        /*
310
                         * XXX shouldn't update any times until successful
311
                         * completion of syscall, but too many callers depend
312
                         * on this.
313
                         *
314
                         * XXX similarly, too many callers depend on
315
                         * ext2_new_inode() setting the times, but error
316
                         * recovery deletes the inode, so the worst that can
317
                         * happen is that the times are slightly out of date
318
                         * and/or different from the directory change time.
319
                         */
320
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
321
                        dir->i_dirt = 1;
322
                        dir->i_version = ++event;
323
                        mark_buffer_dirty(bh, 1);
324
                        *res_dir = de;
325
                        *err = 0;
326
                        return bh;
327
                }
328
                offset += swab16(de->rec_len);
329
                de = (struct ext2_dir_entry *) ((char *) de + swab16(de->rec_len));
330
        }
331
        brelse (bh);
332
        return NULL;
333
}
334
 
335
/*
336
 * ext2_delete_entry deletes a directory entry by merging it with the
337
 * previous entry
338
 */
339
static int ext2_delete_entry (struct ext2_dir_entry * dir,
340
                              struct buffer_head * bh)
341
{
342
        struct ext2_dir_entry * de, * pde;
343
        int i;
344
 
345
        i = 0;
346
        pde = NULL;
347
        de = (struct ext2_dir_entry *) bh->b_data;
348
        while (i < bh->b_size) {
349
                if (!ext2_check_dir_entry ("ext2_delete_entry", NULL,
350
                                           de, bh, i))
351
                        return -EIO;
352
                if (de == dir)  {
353
                        if (pde)
354
                                pde->rec_len =
355
                                        swab16(swab16(pde->rec_len) +
356
                                               swab16(dir->rec_len));
357
                        dir->inode = swab32(0);
358
                        return 0;
359
                }
360
                i += swab16(de->rec_len);
361
                pde = de;
362
                de = (struct ext2_dir_entry *) ((char *) de + swab16(de->rec_len));
363
        }
364
        return -ENOENT;
365
}
366
 
367
int ext2_create (struct inode * dir,const char * name, int len, int mode,
368
                 struct inode ** result)
369
{
370
        struct inode * inode;
371
        struct buffer_head * bh;
372
        struct ext2_dir_entry * de;
373
        int err;
374
 
375
        *result = NULL;
376
        if (!dir)
377
                return -ENOENT;
378
        inode = ext2_new_inode (dir, mode, &err);
379
        if (!inode) {
380
                iput (dir);
381
                return err;
382
        }
383
        inode->i_op = &ext2_file_inode_operations;
384
        inode->i_mode = mode;
385
        inode->i_dirt = 1;
386
        bh = ext2_add_entry (dir, name, len, &de, &err);
387
        if (!bh) {
388
                inode->i_nlink--;
389
                inode->i_dirt = 1;
390
                iput (inode);
391
                iput (dir);
392
                return err;
393
        }
394
        de->inode = swab32(inode->i_ino);
395
        dir->i_version = ++event;
396
        dcache_add(dir, de->name, swab16(de->name_len), swab32(de->inode));
397
        mark_buffer_dirty(bh, 1);
398
        if (IS_SYNC(dir)) {
399
                ll_rw_block (WRITE, 1, &bh);
400
                wait_on_buffer (bh);
401
        }
402
        brelse (bh);
403
        iput (dir);
404
        *result = inode;
405
        return 0;
406
}
407
 
408
int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
409
                int rdev)
410
{
411
        struct inode * inode;
412
        struct buffer_head * bh;
413
        struct ext2_dir_entry * de;
414
        int err;
415
 
416
        if (!dir)
417
                return -ENOENT;
418
 
419
        if (len > EXT2_NAME_LEN) {
420
                iput (dir);
421
                return -ENAMETOOLONG;
422
        }
423
        bh = ext2_find_entry (dir, name, len, &de);
424
        if (bh) {
425
                brelse (bh);
426
                iput (dir);
427
                return -EEXIST;
428
        }
429
        inode = ext2_new_inode (dir, mode, &err);
430
        if (!inode) {
431
                iput (dir);
432
                return err;
433
        }
434
        inode->i_uid = current->fsuid;
435
        inode->i_mode = mode;
436
        inode->i_op = NULL;
437
        if (S_ISREG(inode->i_mode))
438
                inode->i_op = &ext2_file_inode_operations;
439
        else if (S_ISDIR(inode->i_mode)) {
440
                inode->i_op = &ext2_dir_inode_operations;
441
                if (dir->i_mode & S_ISGID)
442
                        inode->i_mode |= S_ISGID;
443
        }
444
        else if (S_ISLNK(inode->i_mode))
445
                inode->i_op = &ext2_symlink_inode_operations;
446
        else if (S_ISCHR(inode->i_mode))
447
                inode->i_op = &chrdev_inode_operations;
448
        else if (S_ISBLK(inode->i_mode))
449
                inode->i_op = &blkdev_inode_operations;
450
        else if (S_ISFIFO(inode->i_mode))
451
                init_fifo(inode);
452
        if (S_ISBLK(mode) || S_ISCHR(mode))
453
                inode->i_rdev = to_kdev_t(rdev);
454
        inode->i_dirt = 1;
455
        bh = ext2_add_entry (dir, name, len, &de, &err);
456
        if (!bh) {
457
                inode->i_nlink--;
458
                inode->i_dirt = 1;
459
                iput (inode);
460
                iput (dir);
461
                return err;
462
        }
463
        de->inode = swab32(inode->i_ino);
464
        dir->i_version = ++event;
465
        dcache_add(dir, de->name, swab16(de->name_len), swab32(de->inode));
466
        mark_buffer_dirty(bh, 1);
467
        if (IS_SYNC(dir)) {
468
                ll_rw_block (WRITE, 1, &bh);
469
                wait_on_buffer (bh);
470
        }
471
        brelse (bh);
472
        iput (dir);
473
        iput (inode);
474
        return 0;
475
}
476
 
477
int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
478
{
479
        struct inode * inode;
480
        struct buffer_head * bh, * dir_block;
481
        struct ext2_dir_entry * de;
482
        int err;
483
 
484
        if (!dir)
485
                return -ENOENT;
486
        if (len > EXT2_NAME_LEN) {
487
                iput (dir);
488
                return -ENAMETOOLONG;
489
        }
490
        bh = ext2_find_entry (dir, name, len, &de);
491
        if (bh) {
492
                brelse (bh);
493
                iput (dir);
494
                return -EEXIST;
495
        }
496
        if (dir->i_nlink >= EXT2_LINK_MAX) {
497
                iput (dir);
498
                return -EMLINK;
499
        }
500
        inode = ext2_new_inode (dir, S_IFDIR, &err);
501
        if (!inode) {
502
                iput (dir);
503
                return err;
504
        }
505
        inode->i_op = &ext2_dir_inode_operations;
506
        inode->i_size = inode->i_sb->s_blocksize;
507
        dir_block = ext2_bread (inode, 0, 1, &err);
508
        if (!dir_block) {
509
                iput (dir);
510
                inode->i_nlink--;
511
                inode->i_dirt = 1;
512
                iput (inode);
513
                return err;
514
        }
515
        inode->i_blocks = inode->i_sb->s_blocksize / 512;
516
        de = (struct ext2_dir_entry *) dir_block->b_data;
517
        de->inode = swab32(inode->i_ino);
518
        de->name_len = swab16(1);
519
        de->rec_len = swab16(EXT2_DIR_REC_LEN(swab16(de->name_len)));
520
        strcpy (de->name, ".");
521
        de = (struct ext2_dir_entry *) ((char *) de + swab16(de->rec_len));
522
        de->inode = swab32(dir->i_ino);
523
        de->rec_len = swab16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
524
        de->name_len = swab16(2);
525
        strcpy (de->name, "..");
526
        inode->i_nlink = 2;
527
        mark_buffer_dirty(dir_block, 1);
528
        brelse (dir_block);
529
        inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
530
        if (dir->i_mode & S_ISGID)
531
                inode->i_mode |= S_ISGID;
532
        inode->i_dirt = 1;
533
        bh = ext2_add_entry (dir, name, len, &de, &err);
534
        if (!bh) {
535
                iput (dir);
536
                inode->i_nlink = 0;
537
                inode->i_dirt = 1;
538
                iput (inode);
539
                return err;
540
        }
541
        de->inode = swab32(inode->i_ino);
542
        dir->i_version = ++event;
543
        dcache_add(dir, de->name, swab16(de->name_len), swab32(de->inode));
544
        mark_buffer_dirty(bh, 1);
545
        if (IS_SYNC(dir)) {
546
                ll_rw_block (WRITE, 1, &bh);
547
                wait_on_buffer (bh);
548
        }
549
        dir->i_nlink++;
550
        dir->i_dirt = 1;
551
        iput (dir);
552
        iput (inode);
553
        brelse (bh);
554
        return 0;
555
}
556
 
557
/*
558
 * routine to check that the specified directory is empty (for rmdir)
559
 */
560
static int empty_dir (struct inode * inode)
561
{
562
        unsigned long offset;
563
        struct buffer_head * bh;
564
        struct ext2_dir_entry * de, * de1;
565
        struct super_block * sb;
566
        int err;
567
 
568
        sb = inode->i_sb;
569
        if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||
570
            !(bh = ext2_bread (inode, 0, 0, &err))) {
571
                ext2_warning (inode->i_sb, "empty_dir",
572
                              "bad directory (dir #%lu) - no data block",
573
                              inode->i_ino);
574
                return 1;
575
        }
576
        de = (struct ext2_dir_entry *) bh->b_data;
577
        de1 = (struct ext2_dir_entry *) ((char *) de + swab16(de->rec_len));
578
        if (swab32(de->inode) != inode->i_ino || !swab32(de1->inode) ||
579
            strcmp (".", de->name) || strcmp ("..", de1->name)) {
580
                ext2_warning (inode->i_sb, "empty_dir",
581
                              "bad directory (dir #%lu) - no `.' or `..'",
582
                              inode->i_ino);
583
                brelse (bh);
584
                return 1;
585
        }
586
        offset = swab16(de->rec_len) + swab16(de1->rec_len);
587
        de = (struct ext2_dir_entry *) ((char *) de1 + swab16(de1->rec_len));
588
        while (offset < inode->i_size ) {
589
                if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
590
                        brelse (bh);
591
                        bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err);
592
                        if (!bh) {
593
                                ext2_error (sb, "empty_dir",
594
                                            "directory #%lu contains a hole at offset %lu",
595
                                            inode->i_ino, offset);
596
                                offset += sb->s_blocksize;
597
                                continue;
598
                        }
599
                        de = (struct ext2_dir_entry *) bh->b_data;
600
                }
601
                if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
602
                                           offset)) {
603
                        brelse (bh);
604
                        return 1;
605
                }
606
                if (swab32(de->inode)) {
607
                        brelse (bh);
608
                        return 0;
609
                }
610
                offset += swab16(de->rec_len);
611
                de = (struct ext2_dir_entry *) ((char *) de + swab16(de->rec_len));
612
        }
613
        brelse (bh);
614
        return 1;
615
}
616
 
617
int ext2_rmdir (struct inode * dir, const char * name, int len)
618
{
619
        int retval;
620
        struct inode * inode;
621
        struct buffer_head * bh;
622
        struct ext2_dir_entry * de;
623
 
624
repeat:
625
        if (!dir)
626
                return -ENOENT;
627
        inode = NULL;
628
        if (len > EXT2_NAME_LEN) {
629
                iput (dir);
630
                return -ENAMETOOLONG;
631
        }
632
        bh = ext2_find_entry (dir, name, len, &de);
633
        retval = -ENOENT;
634
        if (!bh)
635
                goto end_rmdir;
636
        retval = -EPERM;
637
        if (!(inode = iget (dir->i_sb, swab32(de->inode))))
638
                goto end_rmdir;
639
        if (inode->i_sb->dq_op)
640
                inode->i_sb->dq_op->initialize (inode, -1);
641
        if (inode->i_dev != dir->i_dev) {
642
                retval = -EBUSY;
643
                goto end_rmdir;
644
        }
645
        if (swab32(de->inode) != inode->i_ino) {
646
                iput(inode);
647
                brelse(bh);
648
                current->counter = 0;
649
                schedule();
650
                goto repeat;
651
        }
652
        if ((dir->i_mode & S_ISVTX) && !fsuser() &&
653
            current->fsuid != inode->i_uid &&
654
            current->fsuid != dir->i_uid)
655
                goto end_rmdir;
656
        if (inode == dir)       /* we may not delete ".", but "../dir" is ok */
657
                goto end_rmdir;
658
        if (!S_ISDIR(inode->i_mode)) {
659
                retval = -ENOTDIR;
660
                goto end_rmdir;
661
        }
662
        down(&inode->i_sem);
663
        if (!empty_dir (inode))
664
                retval = -ENOTEMPTY;
665
        else if (swab32(de->inode) != inode->i_ino)
666
                retval = -ENOENT;
667
        else {
668
                if (inode->i_count > 1) {
669
                /*
670
                 * Are we deleting the last instance of a busy directory?
671
                 * Better clean up if so.
672
                 *
673
                 * Make directory empty (it will be truncated when finally
674
                 * dereferenced).  This also inhibits ext2_add_entry.
675
                 */
676
                        inode->i_size = 0;
677
                }
678
                retval = ext2_delete_entry (de, bh);
679
                dir->i_version = ++event;
680
        }
681
        up(&inode->i_sem);
682
        if (retval)
683
                goto end_rmdir;
684
        mark_buffer_dirty(bh, 1);
685
        if (IS_SYNC(dir)) {
686
                ll_rw_block (WRITE, 1, &bh);
687
                wait_on_buffer (bh);
688
        }
689
        if (inode->i_nlink != 2)
690
                ext2_warning (inode->i_sb, "ext2_rmdir",
691
                              "empty directory has nlink!=2 (%d)",
692
                              inode->i_nlink);
693
        inode->i_version = ++event;
694
        inode->i_nlink = 0;
695
        inode->i_dirt = 1;
696
        dir->i_nlink--;
697
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
698
        dir->i_dirt = 1;
699
end_rmdir:
700
        iput (dir);
701
        iput (inode);
702
        brelse (bh);
703
        return retval;
704
}
705
 
706
int ext2_unlink (struct inode * dir, const char * name, int len)
707
{
708
        int retval;
709
        struct inode * inode;
710
        struct buffer_head * bh;
711
        struct ext2_dir_entry * de;
712
 
713
repeat:
714
        if (!dir)
715
                return -ENOENT;
716
        retval = -ENOENT;
717
        inode = NULL;
718
        if (len > EXT2_NAME_LEN) {
719
                iput (dir);
720
                return -ENAMETOOLONG;
721
        }
722
        bh = ext2_find_entry (dir, name, len, &de);
723
        if (!bh)
724
                goto end_unlink;
725
        if (!(inode = iget (dir->i_sb, swab32(de->inode))))
726
                goto end_unlink;
727
        if (inode->i_sb->dq_op)
728
                inode->i_sb->dq_op->initialize (inode, -1);
729
        retval = -EPERM;
730
        if (S_ISDIR(inode->i_mode))
731
                goto end_unlink;
732
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
733
                goto end_unlink;
734
        if (swab32(de->inode) != inode->i_ino) {
735
                iput(inode);
736
                brelse(bh);
737
                current->counter = 0;
738
                schedule();
739
                goto repeat;
740
        }
741
        if ((dir->i_mode & S_ISVTX) && !fsuser() &&
742
            current->fsuid != inode->i_uid &&
743
            current->fsuid != dir->i_uid)
744
                goto end_unlink;
745
        if (!inode->i_nlink) {
746
                ext2_warning (inode->i_sb, "ext2_unlink",
747
                              "Deleting nonexistent file (%lu), %d",
748
                              inode->i_ino, inode->i_nlink);
749
                inode->i_nlink = 1;
750
        }
751
        retval = ext2_delete_entry (de, bh);
752
        if (retval)
753
                goto end_unlink;
754
        dir->i_version = ++event;
755
        mark_buffer_dirty(bh, 1);
756
        if (IS_SYNC(dir)) {
757
                ll_rw_block (WRITE, 1, &bh);
758
                wait_on_buffer (bh);
759
        }
760
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
761
        dir->i_dirt = 1;
762
        inode->i_nlink--;
763
        inode->i_dirt = 1;
764
        inode->i_ctime = dir->i_ctime;
765
        retval = 0;
766
end_unlink:
767
        brelse (bh);
768
        iput (inode);
769
        iput (dir);
770
        return retval;
771
}
772
 
773
int ext2_symlink (struct inode * dir, const char * name, int len,
774
                  const char * symname)
775
{
776
        struct ext2_dir_entry * de;
777
        struct inode * inode = NULL;
778
        struct buffer_head * bh = NULL, * name_block = NULL;
779
        char * link;
780
        int i, err;
781
        int l;
782
        char c;
783
 
784
        if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) {
785
                iput (dir);
786
                return err;
787
        }
788
        inode->i_mode = S_IFLNK | S_IRWXUGO;
789
        inode->i_op = &ext2_symlink_inode_operations;
790
        for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
791
             symname [l]; l++)
792
                ;
793
        if (l >= sizeof (inode->u.ext2_i.i_data)) {
794
 
795
                ext2_debug ("l=%d, normal symlink\n", l);
796
 
797
                name_block = ext2_bread (inode, 0, 1, &err);
798
                if (!name_block) {
799
                        iput (dir);
800
                        inode->i_nlink--;
801
                        inode->i_dirt = 1;
802
                        iput (inode);
803
                        return err;
804
                }
805
                link = name_block->b_data;
806
        } else {
807
                link = (char *) inode->u.ext2_i.i_data;
808
 
809
                ext2_debug ("l=%d, fast symlink\n", l);
810
 
811
        }
812
        i = 0;
813
        while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname++)))
814
                link[i++] = c;
815
        link[i] = 0;
816
        if (name_block) {
817
                mark_buffer_dirty(name_block, 1);
818
                brelse (name_block);
819
        }
820
        inode->i_size = i;
821
        inode->i_dirt = 1;
822
 
823
        bh = ext2_find_entry (dir, name, len, &de);
824
        if (bh) {
825
                inode->i_nlink--;
826
                inode->i_dirt = 1;
827
                iput (inode);
828
                brelse (bh);
829
                iput (dir);
830
                return -EEXIST;
831
        }
832
        bh = ext2_add_entry (dir, name, len, &de, &err);
833
        if (!bh) {
834
                inode->i_nlink--;
835
                inode->i_dirt = 1;
836
                iput (inode);
837
                iput (dir);
838
                return err;
839
        }
840
        de->inode = swab32(inode->i_ino);
841
        dir->i_version = ++event;
842
        dcache_add(dir, de->name, swab16(de->name_len), swab32(de->inode));
843
        mark_buffer_dirty(bh, 1);
844
        if (IS_SYNC(dir)) {
845
                ll_rw_block (WRITE, 1, &bh);
846
                wait_on_buffer (bh);
847
        }
848
        brelse (bh);
849
        iput (dir);
850
        iput (inode);
851
        return 0;
852
}
853
 
854
int ext2_link (struct inode * oldinode, struct inode * dir,
855
               const char * name, int len)
856
{
857
        struct ext2_dir_entry * de;
858
        struct buffer_head * bh;
859
        int err;
860
 
861
        if (S_ISDIR(oldinode->i_mode)) {
862
                iput (oldinode);
863
                iput (dir);
864
                return -EPERM;
865
        }
866
        if (IS_APPEND(oldinode) || IS_IMMUTABLE(oldinode)) {
867
                iput (oldinode);
868
                iput (dir);
869
                return -EPERM;
870
        }
871
        if (oldinode->i_nlink >= EXT2_LINK_MAX) {
872
                iput (oldinode);
873
                iput (dir);
874
                return -EMLINK;
875
        }
876
        bh = ext2_find_entry (dir, name, len, &de);
877
        if (bh) {
878
                brelse (bh);
879
                iput (dir);
880
                iput (oldinode);
881
                return -EEXIST;
882
        }
883
        bh = ext2_add_entry (dir, name, len, &de, &err);
884
        if (!bh) {
885
                iput (dir);
886
                iput (oldinode);
887
                return err;
888
        }
889
        de->inode = swab32(oldinode->i_ino);
890
        dir->i_version = ++event;
891
        dcache_add(dir, de->name, swab16(de->name_len), swab32(de->inode));
892
        mark_buffer_dirty(bh, 1);
893
        if (IS_SYNC(dir)) {
894
                ll_rw_block (WRITE, 1, &bh);
895
                wait_on_buffer (bh);
896
        }
897
        brelse (bh);
898
        iput (dir);
899
        oldinode->i_nlink++;
900
        oldinode->i_ctime = CURRENT_TIME;
901
        oldinode->i_dirt = 1;
902
        iput (oldinode);
903
        return 0;
904
}
905
 
906
static int subdir (struct inode * new_inode, struct inode * old_inode)
907
{
908
        int ino;
909
        int result;
910
 
911
        new_inode->i_count++;
912
        result = 0;
913
        for (;;) {
914
                if (new_inode == old_inode) {
915
                        result = 1;
916
                        break;
917
                }
918
                if (new_inode->i_dev != old_inode->i_dev)
919
                        break;
920
                ino = new_inode->i_ino;
921
                if (ext2_lookup (new_inode, "..", 2, &new_inode))
922
                        break;
923
                if (new_inode->i_ino == ino)
924
                        break;
925
        }
926
        iput (new_inode);
927
        return result;
928
}
929
 
930
#define PARENT_INO(buffer) \
931
        ((struct ext2_dir_entry *) ((char *) buffer + \
932
        swab16(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
933
 
934
#define PARENT_NAME(buffer) \
935
        ((struct ext2_dir_entry *) ((char *) buffer + \
936
        swab16(((struct ext2_dir_entry *) buffer)->rec_len)))->name
937
 
938
/*
939
 * rename uses retrying to avoid race-conditions: at least they should be
940
 * minimal.
941
 * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
942
 * checks fail, it tries to restart itself again. Very practical - no changes
943
 * are done until we know everything works ok.. and then all the changes can be
944
 * done in one fell swoop when we have claimed all the buffers needed.
945
 *
946
 * Anybody can rename anything with this: the permission checks are left to the
947
 * higher-level routines.
948
 */
949
static int do_ext2_rename (struct inode * old_dir, const char * old_name,
950
                           int old_len, struct inode * new_dir,
951
                           const char * new_name, int new_len,
952
                           int must_be_dir)
953
{
954
        struct inode * old_inode, * new_inode;
955
        struct buffer_head * old_bh, * new_bh, * dir_bh;
956
        struct ext2_dir_entry * old_de, * new_de;
957
        int retval;
958
 
959
        goto start_up;
960
try_again:
961
        if (new_bh && new_de) {
962
                ext2_delete_entry(new_de, new_bh);
963
                new_dir->i_version = ++event;
964
        }
965
        brelse (old_bh);
966
        brelse (new_bh);
967
        brelse (dir_bh);
968
        iput (old_inode);
969
        iput (new_inode);
970
        current->counter = 0;
971
        schedule ();
972
start_up:
973
        old_inode = new_inode = NULL;
974
        old_bh = new_bh = dir_bh = NULL;
975
        new_de = NULL;
976
        retval = -ENAMETOOLONG;
977
        if (old_len > EXT2_NAME_LEN)
978
                goto end_rename;
979
 
980
        old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de);
981
        retval = -ENOENT;
982
        if (!old_bh)
983
                goto end_rename;
984
        old_inode = __iget (old_dir->i_sb, swab32(old_de->inode), 0); /* don't cross mnt-points */
985
        if (!old_inode)
986
                goto end_rename;
987
        if (must_be_dir && !S_ISDIR(old_inode->i_mode))
988
                goto end_rename;
989
        retval = -EPERM;
990
        if ((old_dir->i_mode & S_ISVTX) &&
991
            current->fsuid != old_inode->i_uid &&
992
            current->fsuid != old_dir->i_uid && !fsuser())
993
                goto end_rename;
994
        if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode))
995
                goto end_rename;
996
        new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
997
        if (new_bh) {
998
                new_inode = __iget (new_dir->i_sb, swab32(new_de->inode), 0); /* no mntp cross */
999
                if (!new_inode) {
1000
                        brelse (new_bh);
1001
                        new_bh = NULL;
1002
                } else {
1003
                        if (new_inode->i_sb->dq_op)
1004
                                new_inode->i_sb->dq_op->initialize (new_inode, -1);
1005
                }
1006
        }
1007
        if (new_inode == old_inode) {
1008
                retval = 0;
1009
                goto end_rename;
1010
        }
1011
        if (new_inode && S_ISDIR(new_inode->i_mode)) {
1012
                retval = -EISDIR;
1013
                if (!S_ISDIR(old_inode->i_mode))
1014
                        goto end_rename;
1015
                retval = -EINVAL;
1016
                if (subdir (new_dir, old_inode))
1017
                        goto end_rename;
1018
                retval = -ENOTEMPTY;
1019
                if (!empty_dir (new_inode))
1020
                        goto end_rename;
1021
                retval = -EBUSY;
1022
                if (new_inode->i_count > 1)
1023
                        goto end_rename;
1024
        }
1025
        retval = -EPERM;
1026
        if (new_inode) {
1027
                if ((new_dir->i_mode & S_ISVTX) &&
1028
                    current->fsuid != new_inode->i_uid &&
1029
                    current->fsuid != new_dir->i_uid && !fsuser())
1030
                        goto end_rename;
1031
                if (IS_APPEND(new_inode) || IS_IMMUTABLE(new_inode))
1032
                        goto end_rename;
1033
        }
1034
 
1035
        if (S_ISDIR(old_inode->i_mode)) {
1036
                retval = -ENOTDIR;
1037
                if (new_inode && !S_ISDIR(new_inode->i_mode))
1038
                        goto end_rename;
1039
                retval = -EINVAL;
1040
                if (subdir (new_dir, old_inode))
1041
                        goto end_rename;
1042
                dir_bh = ext2_bread (old_inode, 0, 0, &retval);
1043
                if (!dir_bh)
1044
                        goto end_rename;
1045
                if (swab32(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
1046
                        goto end_rename;
1047
                retval = -EMLINK;
1048
                if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX)
1049
                        goto end_rename;
1050
        }
1051
        if (!new_bh)
1052
                new_bh = ext2_add_entry (new_dir, new_name, new_len, &new_de,
1053
                                         &retval);
1054
        if (!new_bh)
1055
                goto end_rename;
1056
        new_dir->i_version = ++event;
1057
        /*
1058
         * sanity checking before doing the rename - avoid races
1059
         */
1060
        if (new_inode && (swab32(new_de->inode) != new_inode->i_ino))
1061
                goto try_again;
1062
        if (swab32(new_de->inode) && !new_inode)
1063
                goto try_again;
1064
        if (swab32(old_de->inode) != old_inode->i_ino)
1065
                goto try_again;
1066
        /*
1067
         * ok, that's it
1068
         */
1069
        new_de->inode = swab32(old_inode->i_ino);
1070
        dcache_add(new_dir, new_de->name, swab16(new_de->name_len), swab32(new_de->inode));
1071
        retval = ext2_delete_entry (old_de, old_bh);
1072
        if (retval == -ENOENT)
1073
                goto try_again;
1074
        if (retval)
1075
                goto end_rename;
1076
        old_dir->i_version = ++event;
1077
        if (new_inode) {
1078
                new_inode->i_nlink--;
1079
                new_inode->i_ctime = CURRENT_TIME;
1080
                new_inode->i_dirt = 1;
1081
        }
1082
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1083
        old_dir->i_dirt = 1;
1084
        if (dir_bh) {
1085
                PARENT_INO(dir_bh->b_data) = swab32(new_dir->i_ino);
1086
                dcache_add(old_inode, "..", 2, new_dir->i_ino);
1087
                mark_buffer_dirty(dir_bh, 1);
1088
                old_dir->i_nlink--;
1089
                old_dir->i_dirt = 1;
1090
                if (new_inode) {
1091
                        new_inode->i_nlink--;
1092
                        new_inode->i_dirt = 1;
1093
                } else {
1094
                        new_dir->i_nlink++;
1095
                        new_dir->i_dirt = 1;
1096
                }
1097
        }
1098
        mark_buffer_dirty(old_bh,  1);
1099
        if (IS_SYNC(old_dir)) {
1100
                ll_rw_block (WRITE, 1, &old_bh);
1101
                wait_on_buffer (old_bh);
1102
        }
1103
        mark_buffer_dirty(new_bh, 1);
1104
        if (IS_SYNC(new_dir)) {
1105
                ll_rw_block (WRITE, 1, &new_bh);
1106
                wait_on_buffer (new_bh);
1107
        }
1108
        retval = 0;
1109
end_rename:
1110
        brelse (dir_bh);
1111
        brelse (old_bh);
1112
        brelse (new_bh);
1113
        iput (old_inode);
1114
        iput (new_inode);
1115
        iput (old_dir);
1116
        iput (new_dir);
1117
        return retval;
1118
}
1119
 
1120
/*
1121
 * Ok, rename also locks out other renames, as they can change the parent of
1122
 * a directory, and we don't want any races. Other races are checked for by
1123
 * "do_rename()", which restarts if there are inconsistencies.
1124
 *
1125
 * Note that there is no race between different filesystems: it's only within
1126
 * the same device that races occur: many renames can happen at once, as long
1127
 * as they are on different partitions.
1128
 *
1129
 * In the second extended file system, we use a lock flag stored in the memory
1130
 * super-block.  This way, we really lock other renames only if they occur
1131
 * on the same file system
1132
 */
1133
int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
1134
                 struct inode * new_dir, const char * new_name, int new_len,
1135
                 int must_be_dir)
1136
{
1137
        int result;
1138
 
1139
        while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
1140
                sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
1141
        old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
1142
        result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
1143
                                 new_name, new_len, must_be_dir);
1144
        old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
1145
        wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
1146
        return result;
1147
}

powered by: WebSVN 2.1.0

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