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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/ufs/ufs_dir.c
3
 *
4
 * Copyright (C) 1996
5
 * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
6
 * Laboratory for Computer Science Research Computing Facility
7
 * Rutgers, The State University of New Jersey
8
 *
9
 * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406
10
 *
11
 * 4.4BSD (FreeBSD) support added on February 1st 1998 by
12
 * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
13
 * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
14
 */
15
 
16
#include <linux/sched.h>
17
#include <linux/locks.h>
18
#include <linux/fs.h>
19
#include <linux/ufs_fs.h>
20
 
21
#include "swab.h"
22
#include "util.h"
23
 
24
#undef UFS_DIR_DEBUG
25
 
26
#ifdef UFS_DIR_DEBUG
27
#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
28
#else
29
#define UFSD(x)
30
#endif
31
 
32
 
33
 
34
/*
35
 * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
36
 *
37
 * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
38
 */
39
static inline int ufs_match(struct super_block *sb, int len,
40
                const char * const name, struct ufs_dir_entry * de)
41
{
42
        if (len != ufs_get_de_namlen(sb, de))
43
                return 0;
44
        if (!de->d_ino)
45
                return 0;
46
        return !memcmp(name, de->d_name, len);
47
}
48
 
49
/*
50
 * This is blatantly stolen from ext2fs
51
 */
52
static int
53
ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
54
{
55
        struct inode *inode = filp->f_dentry->d_inode;
56
        int error = 0;
57
        unsigned long offset, lblk, blk;
58
        int i, stored;
59
        struct buffer_head * bh;
60
        struct ufs_dir_entry * de;
61
        struct super_block * sb;
62
        int de_reclen;
63
        unsigned flags;
64
 
65
        sb = inode->i_sb;
66
        flags = sb->u.ufs_sb.s_flags;
67
 
68
        UFSD(("ENTER, ino %lu  f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos))
69
 
70
        stored = 0;
71
        bh = NULL;
72
        offset = filp->f_pos & (sb->s_blocksize - 1);
73
 
74
        while (!error && !stored && filp->f_pos < inode->i_size) {
75
                lblk = (filp->f_pos) >> sb->s_blocksize_bits;
76
                blk = ufs_frag_map(inode, lblk);
77
                if (!blk || !(bh = sb_bread(sb, blk))) {
78
                        /* XXX - error - skip to the next block */
79
                        printk("ufs_readdir: "
80
                               "dir inode %lu has a hole at offset %lu\n",
81
                               inode->i_ino, (unsigned long int)filp->f_pos);
82
                        filp->f_pos += sb->s_blocksize - offset;
83
                        continue;
84
                }
85
 
86
revalidate:
87
                /* If the dir block has changed since the last call to
88
                 * readdir(2), then we might be pointing to an invalid
89
                 * dirent right now.  Scan from the start of the block
90
                 * to make sure. */
91
                if (filp->f_version != inode->i_version) {
92
                        for (i = 0; i < sb->s_blocksize && i < offset; ) {
93
                                de = (struct ufs_dir_entry *)(bh->b_data + i);
94
                                /* It's too expensive to do a full
95
                                 * dirent test each time round this
96
                                 * loop, but we do have to test at
97
                                 * least that it is non-zero.  A
98
                                 * failure will be detected in the
99
                                 * dirent test below. */
100
                                de_reclen = fs16_to_cpu(sb, de->d_reclen);
101
                                if (de_reclen < 1)
102
                                        break;
103
                                i += de_reclen;
104
                        }
105
                        offset = i;
106
                        filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
107
                                | offset;
108
                        filp->f_version = inode->i_version;
109
                }
110
 
111
                while (!error && filp->f_pos < inode->i_size
112
                       && offset < sb->s_blocksize) {
113
                        de = (struct ufs_dir_entry *) (bh->b_data + offset);
114
                        /* XXX - put in a real ufs_check_dir_entry() */
115
                        if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
116
                                filp->f_pos = (filp->f_pos &
117
                                              (sb->s_blocksize - 1)) +
118
                                               sb->s_blocksize;
119
                                brelse(bh);
120
                                return stored;
121
                        }
122
                        if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
123
                                                   bh, offset)) {
124
                                /* On error, skip the f_pos to the
125
                                   next block. */
126
                                filp->f_pos = (filp->f_pos |
127
                                              (sb->s_blocksize - 1)) +
128
                                               1;
129
                                brelse (bh);
130
                                return stored;
131
                        }
132
                        offset += fs16_to_cpu(sb, de->d_reclen);
133
                        if (de->d_ino) {
134
                                /* We might block in the next section
135
                                 * if the data destination is
136
                                 * currently swapped out.  So, use a
137
                                 * version stamp to detect whether or
138
                                 * not the directory has been modified
139
                                 * during the copy operation. */
140
                                unsigned long version = filp->f_version;
141
                                unsigned char d_type = DT_UNKNOWN;
142
 
143
                                UFSD(("filldir(%s,%u)\n", de->d_name,
144
                                                        fs32_to_cpu(sb, de->d_ino)))
145
                                UFSD(("namlen %u\n", ufs_get_de_namlen(sb, de)))
146
 
147
                                if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
148
                                        d_type = de->d_u.d_44.d_type;
149
                                error = filldir(dirent, de->d_name,
150
                                                ufs_get_de_namlen(sb, de), filp->f_pos,
151
                                                fs32_to_cpu(sb, de->d_ino), d_type);
152
                                if (error)
153
                                        break;
154
                                if (version != filp->f_version)
155
                                        goto revalidate;
156
                                stored ++;
157
                        }
158
                        filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
159
                }
160
                offset = 0;
161
                brelse (bh);
162
        }
163
        UPDATE_ATIME(inode);
164
        return 0;
165
}
166
 
167
/*
168
 * define how far ahead to read directories while searching them.
169
 */
170
#define NAMEI_RA_CHUNKS  2
171
#define NAMEI_RA_BLOCKS  4
172
#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
173
#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
174
 
175
/*
176
 *      ufs_find_entry()
177
 *
178
 * finds an entry in the specified directory with the wanted name. It
179
 * returns the cache buffer in which the entry was found, and the entry
180
 * itself (as a parameter - res_bh). It does NOT read the inode of the
181
 * entry - you'll have to do that yourself if you want to.
182
 */
183
struct ufs_dir_entry * ufs_find_entry (struct dentry *dentry,
184
        struct buffer_head ** res_bh)
185
{
186
        struct super_block * sb;
187
        struct buffer_head * bh_use[NAMEI_RA_SIZE];
188
        struct buffer_head * bh_read[NAMEI_RA_SIZE];
189
        unsigned long offset;
190
        int block, toread, i, err;
191
        struct inode *dir = dentry->d_parent->d_inode;
192
        const char *name = dentry->d_name.name;
193
        int namelen = dentry->d_name.len;
194
 
195
        UFSD(("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen))
196
 
197
        *res_bh = NULL;
198
 
199
        sb = dir->i_sb;
200
 
201
        if (namelen > UFS_MAXNAMLEN)
202
                return NULL;
203
 
204
        memset (bh_use, 0, sizeof (bh_use));
205
        toread = 0;
206
        for (block = 0; block < NAMEI_RA_SIZE; ++block) {
207
                struct buffer_head * bh;
208
 
209
                if ((block << sb->s_blocksize_bits) >= dir->i_size)
210
                        break;
211
                bh = ufs_getfrag (dir, block, 0, &err);
212
                bh_use[block] = bh;
213
                if (bh && !buffer_uptodate(bh))
214
                        bh_read[toread++] = bh;
215
        }
216
 
217
        for (block = 0, offset = 0; offset < dir->i_size; block++) {
218
                struct buffer_head * bh;
219
                struct ufs_dir_entry * de;
220
                char * dlimit;
221
 
222
                if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
223
                        ll_rw_block (READ, toread, bh_read);
224
                        toread = 0;
225
                }
226
                bh = bh_use[block % NAMEI_RA_SIZE];
227
                if (!bh) {
228
                        ufs_error (sb, "ufs_find_entry",
229
                                "directory #%lu contains a hole at offset %lu",
230
                                dir->i_ino, offset);
231
                        offset += sb->s_blocksize;
232
                        continue;
233
                }
234
                wait_on_buffer (bh);
235
                if (!buffer_uptodate(bh)) {
236
                        /*
237
                         * read error: all bets are off
238
                         */
239
                        break;
240
                }
241
 
242
                de = (struct ufs_dir_entry *) bh->b_data;
243
                dlimit = bh->b_data + sb->s_blocksize;
244
                while ((char *) de < dlimit && offset < dir->i_size) {
245
                        /* this code is executed quadratically often */
246
                        /* do minimal checking by hand */
247
                        int de_len;
248
 
249
                        if ((char *) de + namelen <= dlimit &&
250
                            ufs_match(sb, namelen, name, de)) {
251
                                /* found a match -
252
                                just to be sure, do a full check */
253
                                if (!ufs_check_dir_entry("ufs_find_entry",
254
                                    dir, de, bh, offset))
255
                                        goto failed;
256
                                for (i = 0; i < NAMEI_RA_SIZE; ++i) {
257
                                        if (bh_use[i] != bh)
258
                                                brelse (bh_use[i]);
259
                                }
260
                                *res_bh = bh;
261
                                return de;
262
                        }
263
                        /* prevent looping on a bad block */
264
                        de_len = fs16_to_cpu(sb, de->d_reclen);
265
                        if (de_len <= 0)
266
                                goto failed;
267
                        offset += de_len;
268
                        de = (struct ufs_dir_entry *) ((char *) de + de_len);
269
                }
270
 
271
                brelse (bh);
272
                if (((block + NAMEI_RA_SIZE) << sb->s_blocksize_bits ) >=
273
                    dir->i_size)
274
                        bh = NULL;
275
                else
276
                        bh = ufs_getfrag (dir, block + NAMEI_RA_SIZE, 0, &err);
277
                bh_use[block % NAMEI_RA_SIZE] = bh;
278
                if (bh && !buffer_uptodate(bh))
279
                        bh_read[toread++] = bh;
280
        }
281
 
282
failed:
283
        for (i = 0; i < NAMEI_RA_SIZE; ++i) brelse (bh_use[i]);
284
        UFSD(("EXIT\n"))
285
        return NULL;
286
}
287
 
288
int ufs_check_dir_entry (const char * function, struct inode * dir,
289
        struct ufs_dir_entry * de, struct buffer_head * bh,
290
        unsigned long offset)
291
{
292
        struct super_block *sb = dir->i_sb;
293
        const char *error_msg = NULL;
294
        int rlen = fs16_to_cpu(sb, de->d_reclen);
295
 
296
        if (rlen < UFS_DIR_REC_LEN(1))
297
                error_msg = "reclen is smaller than minimal";
298
        else if (rlen % 4 != 0)
299
                error_msg = "reclen % 4 != 0";
300
        else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
301
                error_msg = "reclen is too small for namlen";
302
        else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
303
                error_msg = "directory entry across blocks";
304
        else if (fs32_to_cpu(sb, de->d_ino) > (sb->u.ufs_sb.s_uspi->s_ipg *
305
                                      sb->u.ufs_sb.s_uspi->s_ncg))
306
                error_msg = "inode out of bounds";
307
 
308
        if (error_msg != NULL)
309
                ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
310
                            "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
311
                            dir->i_ino, dir->i_size, error_msg, offset,
312
                            (unsigned long)fs32_to_cpu(sb, de->d_ino),
313
                            rlen, ufs_get_de_namlen(sb, de));
314
 
315
        return (error_msg == NULL ? 1 : 0);
316
}
317
 
318
struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p)
319
{
320
        int err;
321
        struct buffer_head *bh = ufs_bread (dir, 0, 0, &err);
322
        struct ufs_dir_entry *res = NULL;
323
 
324
        if (bh) {
325
                res = (struct ufs_dir_entry *) bh->b_data;
326
                res = (struct ufs_dir_entry *)((char *)res +
327
                        fs16_to_cpu(dir->i_sb, res->d_reclen));
328
        }
329
        *p = bh;
330
        return res;
331
}
332
ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
333
{
334
        ino_t res = 0;
335
        struct ufs_dir_entry * de;
336
        struct buffer_head *bh;
337
 
338
        de = ufs_find_entry (dentry, &bh);
339
        if (de) {
340
                res = fs32_to_cpu(dir->i_sb, de->d_ino);
341
                brelse(bh);
342
        }
343
        return res;
344
}
345
 
346
void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
347
                struct buffer_head *bh, struct inode *inode)
348
{
349
        dir->i_version = ++event;
350
        de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
351
        mark_buffer_dirty(bh);
352
        if (IS_SYNC(dir)) {
353
                ll_rw_block (WRITE, 1, &bh);
354
                wait_on_buffer(bh);
355
        }
356
        brelse (bh);
357
}
358
 
359
/*
360
 *      ufs_add_entry()
361
 *
362
 * adds a file entry to the specified directory, using the same
363
 * semantics as ufs_find_entry(). It returns NULL if it failed.
364
 */
365
int ufs_add_link(struct dentry *dentry, struct inode *inode)
366
{
367
        struct super_block * sb;
368
        struct ufs_sb_private_info * uspi;
369
        unsigned long offset;
370
        unsigned fragoff;
371
        unsigned short rec_len;
372
        struct buffer_head * bh;
373
        struct ufs_dir_entry * de, * de1;
374
        struct inode *dir = dentry->d_parent->d_inode;
375
        const char *name = dentry->d_name.name;
376
        int namelen = dentry->d_name.len;
377
        int err;
378
 
379
        UFSD(("ENTER, name %s, namelen %u\n", name, namelen))
380
 
381
        sb = dir->i_sb;
382
        uspi = sb->u.ufs_sb.s_uspi;
383
 
384
        if (!namelen)
385
                return -EINVAL;
386
        bh = ufs_bread (dir, 0, 0, &err);
387
        if (!bh)
388
                return err;
389
        rec_len = UFS_DIR_REC_LEN(namelen);
390
        offset = 0;
391
        de = (struct ufs_dir_entry *) bh->b_data;
392
        while (1) {
393
                if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) {
394
                        fragoff = offset & ~uspi->s_fmask;
395
                        if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE)
396
                                ufs_error (sb, "ufs_add_entry", "internal error"
397
                                        " fragoff %u", fragoff);
398
                        if (!fragoff) {
399
                                brelse (bh);
400
                                bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err);
401
                                if (!bh)
402
                                        return err;
403
                        }
404
                        if (dir->i_size <= offset) {
405
                                if (dir->i_size == 0) {
406
                                        brelse(bh);
407
                                        return -ENOENT;
408
                                }
409
                                de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
410
                                de->d_ino = 0;
411
                                de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
412
                                ufs_set_de_namlen(sb, de, 0);
413
                                dir->i_size = offset + UFS_SECTOR_SIZE;
414
                                mark_inode_dirty(dir);
415
                        } else {
416
                                de = (struct ufs_dir_entry *) bh->b_data;
417
                        }
418
                }
419
                if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) {
420
                        brelse (bh);
421
                        return -ENOENT;
422
                }
423
                if (ufs_match(sb, namelen, name, de)) {
424
                        brelse (bh);
425
                        return -EEXIST;
426
                }
427
                if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
428
                        break;
429
 
430
                if (fs16_to_cpu(sb, de->d_reclen) >=
431
                     UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
432
                        break;
433
                offset += fs16_to_cpu(sb, de->d_reclen);
434
                de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
435
        }
436
 
437
        if (de->d_ino) {
438
                de1 = (struct ufs_dir_entry *) ((char *) de +
439
                        UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
440
                de1->d_reclen =
441
                        cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
442
                                UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
443
                de->d_reclen =
444
                        cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
445
                de = de1;
446
        }
447
        de->d_ino = 0;
448
        ufs_set_de_namlen(sb, de, namelen);
449
        memcpy (de->d_name, name, namelen + 1);
450
        de->d_ino = cpu_to_fs32(sb, inode->i_ino);
451
        ufs_set_de_type(sb, de, inode->i_mode);
452
        mark_buffer_dirty(bh);
453
        if (IS_SYNC(dir)) {
454
                ll_rw_block (WRITE, 1, &bh);
455
                wait_on_buffer (bh);
456
        }
457
        brelse (bh);
458
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
459
        dir->i_version = ++event;
460
        mark_inode_dirty(dir);
461
 
462
        UFSD(("EXIT\n"))
463
        return 0;
464
}
465
 
466
/*
467
 * ufs_delete_entry deletes a directory entry by merging it with the
468
 * previous entry.
469
 */
470
int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
471
        struct buffer_head * bh )
472
 
473
{
474
        struct super_block * sb;
475
        struct ufs_dir_entry * de, * pde;
476
        unsigned i;
477
 
478
        UFSD(("ENTER\n"))
479
 
480
        sb = inode->i_sb;
481
        i = 0;
482
        pde = NULL;
483
        de = (struct ufs_dir_entry *) bh->b_data;
484
 
485
        UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
486
                fs32_to_cpu(sb, de->d_ino),
487
                fs16to_cpu(sb, de->d_reclen),
488
                ufs_get_de_namlen(sb, de), de->d_name))
489
 
490
        while (i < bh->b_size) {
491
                if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
492
                        brelse(bh);
493
                        return -EIO;
494
                }
495
                if (de == dir)  {
496
                        if (pde)
497
                                fs16_add(sb, &pde->d_reclen,
498
                                        fs16_to_cpu(sb, dir->d_reclen));
499
                        dir->d_ino = 0;
500
                        inode->i_version = ++event;
501
                        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
502
                        mark_inode_dirty(inode);
503
                        mark_buffer_dirty(bh);
504
                        if (IS_SYNC(inode)) {
505
                                ll_rw_block(WRITE, 1, &bh);
506
                                wait_on_buffer(bh);
507
                        }
508
                        brelse(bh);
509
                        UFSD(("EXIT\n"))
510
                        return 0;
511
                }
512
                i += fs16_to_cpu(sb, de->d_reclen);
513
                if (i == UFS_SECTOR_SIZE) pde = NULL;
514
                else pde = de;
515
                de = (struct ufs_dir_entry *)
516
                    ((char *) de + fs16_to_cpu(sb, de->d_reclen));
517
                if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
518
                        break;
519
        }
520
        UFSD(("EXIT\n"))
521
        brelse(bh);
522
        return -ENOENT;
523
}
524
 
525
int ufs_make_empty(struct inode * inode, struct inode *dir)
526
{
527
        struct super_block * sb = dir->i_sb;
528
        struct buffer_head * dir_block;
529
        struct ufs_dir_entry * de;
530
        int err;
531
 
532
        dir_block = ufs_bread (inode, 0, 1, &err);
533
        if (!dir_block)
534
                return err;
535
 
536
        inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
537
        de = (struct ufs_dir_entry *) dir_block->b_data;
538
        de->d_ino = cpu_to_fs32(sb, inode->i_ino);
539
        ufs_set_de_type(sb, de, inode->i_mode);
540
        ufs_set_de_namlen(sb, de, 1);
541
        de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));
542
        strcpy (de->d_name, ".");
543
        de = (struct ufs_dir_entry *)
544
                ((char *)de + fs16_to_cpu(sb, de->d_reclen));
545
        de->d_ino = cpu_to_fs32(sb, dir->i_ino);
546
        ufs_set_de_type(sb, de, dir->i_mode);
547
        de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
548
        ufs_set_de_namlen(sb, de, 2);
549
        strcpy (de->d_name, "..");
550
        mark_buffer_dirty(dir_block);
551
        brelse (dir_block);
552
        mark_inode_dirty(inode);
553
        return 0;
554
}
555
 
556
/*
557
 * routine to check that the specified directory is empty (for rmdir)
558
 */
559
int ufs_empty_dir (struct inode * inode)
560
{
561
        struct super_block * sb;
562
        unsigned long offset;
563
        struct buffer_head * bh;
564
        struct ufs_dir_entry * de, * de1;
565
        int err;
566
 
567
        sb = inode->i_sb;
568
 
569
        if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
570
            !(bh = ufs_bread (inode, 0, 0, &err))) {
571
                ufs_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 ufs_dir_entry *) bh->b_data;
577
        de1 = (struct ufs_dir_entry *)
578
                ((char *)de + fs16_to_cpu(sb, de->d_reclen));
579
        if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
580
             strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
581
                ufs_warning (inode->i_sb, "empty_dir",
582
                              "bad directory (dir #%lu) - no `.' or `..'",
583
                              inode->i_ino);
584
                return 1;
585
        }
586
        offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
587
        de = (struct ufs_dir_entry *)
588
                ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
589
        while (offset < inode->i_size ) {
590
                if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
591
                        brelse (bh);
592
                        bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
593
                        if (!bh) {
594
                                ufs_error (sb, "empty_dir",
595
                                            "directory #%lu contains a hole at offset %lu",
596
                                            inode->i_ino, offset);
597
                                offset += sb->s_blocksize;
598
                                continue;
599
                        }
600
                        de = (struct ufs_dir_entry *) bh->b_data;
601
                }
602
                if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {
603
                        brelse (bh);
604
                        return 1;
605
                }
606
                if (de->d_ino) {
607
                        brelse (bh);
608
                        return 0;
609
                }
610
                offset += fs16_to_cpu(sb, de->d_reclen);
611
                de = (struct ufs_dir_entry *)
612
                        ((char *)de + fs16_to_cpu(sb, de->d_reclen));
613
        }
614
        brelse (bh);
615
        return 1;
616
}
617
 
618
struct file_operations ufs_dir_operations = {
619
        read:           generic_read_dir,
620
        readdir:        ufs_readdir,
621
        fsync:          file_fsync,
622
};

powered by: WebSVN 2.1.0

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