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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [dir.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/affs/dir.c
3
 *
4
 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
5
 *
6
 *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
7
 *
8
 *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
9
 *
10
 *  (C) 1991  Linus Torvalds - minix filesystem
11
 *
12
 *  affs directory handling functions
13
 *
14
 */
15
 
16
#include <asm/segment.h>
17
#include <linux/errno.h>
18
#include <linux/fs.h>
19
#include <linux/kernel.h>
20
#include <linux/affs_fs.h>
21
#include <linux/stat.h>
22
#include <linux/string.h>
23
#include <linux/mm.h>
24
#include <linux/amigaffs.h>
25
 
26
static int affs_readdir(struct inode *, struct file *, void *, filldir_t);
27
static int affs_dir_read(struct inode * inode, struct file * filp, char * buf, int count);
28
 
29
static struct file_operations affs_dir_operations = {
30
        NULL,                   /* lseek - default */
31
        affs_dir_read,          /* read */
32
        NULL,                   /* write - bad */
33
        affs_readdir,           /* readdir */
34
        NULL,                   /* select - default */
35
        NULL,                   /* ioctl - default */
36
        NULL,                   /* mmap */
37
        NULL,                   /* no special open code */
38
        NULL,                   /* no special release code */
39
        file_fsync              /* default fsync */
40
};
41
 
42
/*
43
 * directories can handle most operations...
44
 */
45
struct inode_operations affs_dir_inode_operations = {
46
        &affs_dir_operations,   /* default directory file-ops */
47
        affs_create,            /* create */
48
        affs_lookup,            /* lookup */
49
        affs_link,              /* link */
50
        affs_unlink,            /* unlink */
51
        affs_symlink,           /* symlink */
52
        affs_mkdir,             /* mkdir */
53
        affs_rmdir,             /* rmdir */
54
        NULL,                   /* mknod */
55
        affs_rename,            /* rename */
56
        NULL,                   /* readlink */
57
        NULL,                   /* follow_link */
58
        NULL,                   /* readpage */
59
        NULL,                   /* writepage */
60
        NULL,                   /* bmap */
61
        NULL,                   /* truncate */
62
        NULL                    /* permissions */
63
};
64
 
65
static int
66
affs_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
67
{
68
        return -EISDIR;
69
}
70
 
71
static int
72
affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir)
73
{
74
        int                      j, namelen;
75
        int                      i;
76
        int                      hash_pos;
77
        int                      chain_pos;
78
        unsigned long            ino;
79
        unsigned long            old;
80
        int stored;
81
        char *name;
82
        struct buffer_head *dir_bh;
83
        struct buffer_head *fh_bh;
84
        struct inode       *dir;
85
 
86
        pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos);
87
 
88
 
89
        if (!inode || !S_ISDIR(inode->i_mode))
90
                return -EBADF;
91
 
92
        stored = 0;
93
        dir_bh = NULL;
94
        fh_bh  = NULL;
95
        dir    = NULL;
96
        old    = filp->f_pos & 0x80000000;
97
        filp->f_pos &= 0x7FFFFFFF;
98
 
99
        if (filp->f_pos == 0) {
100
                filp->private_data = (void *)0;
101
                if (filldir(dirent,".",1,filp->f_pos,inode->i_ino) < 0) {
102
                        return 0;
103
                }
104
                ++filp->f_pos;
105
                stored++;
106
        }
107
        if (filp->f_pos == 1) {
108
                if (filldir(dirent,"..",2,filp->f_pos,affs_parent_ino(inode)) < 0) {
109
                        filp->f_pos |= 0x80000000;
110
                        return stored;
111
                }
112
                filp->f_pos = 2;
113
                stored++;
114
        }
115
 
116
        /* Read original if this is a link */
117
        ino = inode->u.affs_i.i_original ? inode->u.affs_i.i_original : inode->i_ino;
118
        if (!(dir = iget(inode->i_sb,ino)))
119
                return stored;
120
 
121
        chain_pos = (filp->f_pos - 2) & 0xffff;
122
        hash_pos  = (filp->f_pos - 2) >> 16;
123
        if (chain_pos == 0xffff) {
124
                printk("AFFS: more than 65535 entries in chain\n");
125
                chain_pos = 0;
126
                hash_pos++;
127
                filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
128
        }
129
        if (!(dir_bh = affs_bread(inode->i_dev,ino,AFFS_I2BSIZE(inode))))
130
                goto readdir_done;
131
 
132
        while (!stored || !old) {
133
                while (hash_pos < AFFS_I2HSIZE(inode) &&
134
                     !((struct dir_front *)dir_bh->b_data)->hashtable[hash_pos])
135
                        hash_pos++;
136
                if (hash_pos >= AFFS_I2HSIZE(inode))
137
                        goto readdir_done;
138
 
139
                i = htonl(((struct dir_front *)dir_bh->b_data)->hashtable[hash_pos]);
140
                j = chain_pos;
141
                /* If the directory hasn't changed since the last call to readdir(),
142
                 * we can jump directly to where we left off.
143
                 */
144
                if (filp->private_data && filp->f_version == dir->i_version) {
145
                        i = (int)filp->private_data;
146
                        j = 0;
147
                        pr_debug("AFFS: readdir() left off=%d\n",i);
148
                }
149
                filp->f_version = dir->i_version;
150
                pr_debug("AFFS: hash_pos=%lu chain_pos=%lu\n", hash_pos, chain_pos);
151
                while (i) {
152
                        if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) {
153
                                printk("AFFS: readdir: Can't get block %d\n",i);
154
                                goto readdir_done;
155
                        }
156
                        ino = i;
157
                        i   = htonl(FILE_END(fh_bh->b_data,inode)->hash_chain);
158
                        if (j == 0)
159
                                break;
160
                        affs_brelse(fh_bh);
161
                        fh_bh = NULL;
162
                        j--;
163
                }
164
                if (fh_bh) {
165
                        namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name);
166
                        pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%lu\n",
167
                                 namelen,name,ino,i);
168
                        filp->private_data = (void *)ino;
169
                        if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0)
170
                                goto readdir_done;
171
                        filp->private_data = (void *)i;
172
                        affs_brelse(fh_bh);
173
                        fh_bh = NULL;
174
                        stored++;
175
                }
176
                if (i == 0) {
177
                        hash_pos++;
178
                        chain_pos = 0;
179
                } else
180
                        chain_pos++;
181
                filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
182
        }
183
 
184
readdir_done:
185
        filp->f_pos |= old;
186
        affs_brelse(dir_bh);
187
        affs_brelse(fh_bh);
188
        iput(dir);
189
        pr_debug("AFFS: readdir()=%d\n",stored);
190
        return stored;
191
}

powered by: WebSVN 2.1.0

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