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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/isofs/dir.c
3
 *
4
 *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
5
 *
6
 *  (C) 1991  Linus Torvalds - minix filesystem
7
 *
8
 *  Steve Beynon                       : Missing last directory entries fixed
9
 *  (stephen@askone.demon.co.uk)      : 21st June 1996
10
 *
11
 *  isofs directory handling functions
12
 */
13
#include <linux/errno.h>
14
#include <linux/fs.h>
15
#include <linux/iso_fs.h>
16
#include <linux/kernel.h>
17
#include <linux/stat.h>
18
#include <linux/string.h>
19
#include <linux/mm.h>
20
#include <linux/malloc.h>
21
#include <linux/sched.h>
22
#include <linux/locks.h>
23
 
24
#include <asm/segment.h>
25
 
26
 
27
static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
28
 
29
static struct file_operations isofs_dir_operations =
30
{
31
        NULL,                   /* lseek - default */
32
        NULL,                   /* read */
33
        NULL,                   /* write - bad */
34
        isofs_readdir,          /* readdir */
35
        NULL,                   /* select - default */
36
        NULL,                   /* ioctl - default */
37
        NULL,                   /* no special open code */
38
        NULL,                   /* no special release code */
39
        NULL                    /* fsync */
40
};
41
 
42
/*
43
 * directories can handle most operations...
44
 */
45
struct inode_operations isofs_dir_inode_operations =
46
{
47
        &isofs_dir_operations,  /* default directory file-ops */
48
        NULL,                   /* create */
49
        isofs_lookup,           /* lookup */
50
        NULL,                   /* link */
51
        NULL,                   /* unlink */
52
        NULL,                   /* symlink */
53
        NULL,                   /* mkdir */
54
        NULL,                   /* rmdir */
55
        NULL,                   /* mknod */
56
        NULL,                   /* rename */
57
        NULL,                   /* readlink */
58
        NULL,                   /* follow_link */
59
        NULL,                   /* readpage */
60
        NULL,                   /* writepage */
61
        isofs_bmap,             /* bmap */
62
        NULL,                   /* truncate */
63
        NULL                    /* permission */
64
};
65
 
66
static int parent_inode_number(struct inode * inode, struct iso_directory_record * de)
67
{
68
        int inode_number = inode->i_ino;
69
 
70
        if ((inode->i_sb->u.isofs_sb.s_firstdatazone) != inode->i_ino)
71
                inode_number = inode->u.isofs_i.i_backlink;
72
 
73
        if (inode_number != -1)
74
                return inode_number;
75
 
76
        /* This should never happen, but who knows.  Try to be forgiving */
77
        return isofs_lookup_grandparent(inode, find_rock_ridge_relocation(de, inode));
78
}
79
 
80
static int isofs_name_translate(char * old, int len, char * new)
81
{
82
        int i, c;
83
 
84
        for (i = 0; i < len; i++) {
85
                c = old[i];
86
                if (!c)
87
                        break;
88
                if (c >= 'A' && c <= 'Z')
89
                        c |= 0x20;      /* lower case */
90
 
91
                /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
92
                if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
93
                        break;
94
 
95
                /* Drop trailing ';1' */
96
                if (c == ';' && i == len - 2 && old[i + 1] == '1')
97
                        break;
98
 
99
                /* Convert remaining ';' to '.' */
100
                if (c == ';')
101
                        c = '.';
102
 
103
                new[i] = c;
104
        }
105
        return i;
106
}
107
 
108
/*
109
 * This should _really_ be cleaned up some day..
110
 */
111
static int do_isofs_readdir(struct inode *inode, struct file *filp,
112
                void *dirent, filldir_t filldir,
113
                char * tmpname, struct iso_directory_record * tmpde)
114
{
115
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
116
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
117
        unsigned int block, offset;
118
        int inode_number = 0;    /* Quiet GCC */
119
        struct buffer_head *bh;
120
        int len;
121
        int map;
122
        int high_sierra;
123
        int first_de = 1;
124
        char *p = NULL;         /* Quiet GCC */
125
        struct iso_directory_record *de;
126
 
127
        offset = filp->f_pos & (bufsize - 1);
128
        block = isofs_bmap(inode, filp->f_pos >> bufbits);
129
        high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
130
 
131
        if (!block)
132
                return 0;
133
 
134
        if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
135
                return 0;
136
 
137
        while (filp->f_pos < inode->i_size) {
138
                int de_len, next_offset;
139
#ifdef DEBUG
140
                printk("Block, offset, f_pos: %x %x %x\n",
141
                       block, offset, filp->f_pos);
142
                printk("inode->i_size = %x\n",inode->i_size);
143
#endif
144
                /* Next directory_record on next CDROM sector */
145
                if (offset >= bufsize) {
146
#ifdef DEBUG
147
                        printk("offset >= bufsize\n");
148
#endif
149
                        brelse(bh);
150
                        offset = 0;
151
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
152
                        if (!block)
153
                                return 0;
154
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
155
                        if (!bh)
156
                                return 0;
157
                        continue;
158
                }
159
 
160
                de = (struct iso_directory_record *) (bh->b_data + offset);
161
                if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
162
 
163
                de_len = *(unsigned char *) de;
164
#ifdef DEBUG
165
                printk("de_len = %ld\n", de_len);
166
#endif
167
 
168
 
169
                /* If the length byte is zero, we should move on to the next
170
                   CDROM sector.  If we are at the end of the directory, we
171
                   kick out of the while loop. */
172
 
173
                if (de_len == 0) {
174
                        brelse(bh);
175
                        filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
176
                                       + ISOFS_BLOCK_SIZE);
177
                        offset = 0;
178
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
179
                        if (!block)
180
                                return 0;
181
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
182
                        if (!bh)
183
                                return 0;
184
                        continue;
185
                }
186
 
187
                /* Make sure that the entire directory record is in the
188
                   current bh block.
189
                   If not, put the two halves together in "tmpde" */
190
                next_offset = offset + de_len;
191
                if (next_offset > bufsize) {
192
#ifdef DEBUG
193
                        printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
194
#endif
195
                        next_offset &= (bufsize - 1);
196
                        memcpy(tmpde, de, bufsize - offset);
197
                        brelse(bh);
198
                        block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
199
                        if (!block)
200
                        {
201
                                return 0;
202
                        }
203
 
204
                        bh = breada(inode->i_dev, block, bufsize,
205
                                    filp->f_pos,
206
                                    inode->i_size);
207
                        if (!bh)
208
                        {
209
#ifdef DEBUG
210
                                printk("!bh block=%ld, bufsize=%ld\n",block,bufsize);
211
                                printk("filp->f_pos = %ld\n",filp->f_pos);
212
                                printk("inode->i_size = %ld\n", inode->i_size);
213
#endif
214
                                return 0;
215
                        }
216
 
217
                        memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
218
                        de = tmpde;
219
                }
220
                offset = next_offset;
221
 
222
                if(de->flags[-high_sierra] & 0x80) {
223
                        first_de = 0;
224
                        filp->f_pos += de_len;
225
                        continue;
226
                }
227
                first_de = 1;
228
 
229
                /* Handle the case of the '.' directory */
230
                if (de->name_len[0] == 1 && de->name[0] == 0) {
231
                        if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
232
                                break;
233
                        filp->f_pos += de_len;
234
                        continue;
235
                }
236
 
237
                len = 0;
238
 
239
                /* Handle the case of the '..' directory */
240
                if (de->name_len[0] == 1 && de->name[0] == 1) {
241
                        inode_number = parent_inode_number(inode, de);
242
                        if (inode_number == -1)
243
                                break;
244
                        if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
245
                                break;
246
                        filp->f_pos += de_len;
247
                        continue;
248
                }
249
 
250
                /* Handle everything else.  Do name translation if there
251
                   is no Rock Ridge NM field. */
252
                if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
253
                        /* Do not report hidden or associated files */
254
                        if (de->flags[-high_sierra] & 5) {
255
                                filp->f_pos += de_len;
256
                                continue;
257
                        }
258
                }
259
 
260
                map = 1;
261
                if (inode->i_sb->u.isofs_sb.s_rock) {
262
                        len = get_rock_ridge_filename(de, tmpname, inode);
263
                        if (len != 0) {
264
                                p = tmpname;
265
                                map = 0;
266
                        }
267
                }
268
                if (map) {
269
                        if (inode->i_sb->u.isofs_sb.s_joliet_level) {
270
                                len = get_joliet_filename(de, inode, tmpname);
271
                                p = tmpname;
272
                        } else {
273
                                if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
274
                                        len = isofs_name_translate(de->name, de->name_len[0],
275
                                                                   tmpname);
276
                                        p = tmpname;
277
                                } else {
278
                                        p = de->name;
279
                                        len = de->name_len[0];
280
                                }
281
                        }
282
                }
283
                if (len > 0) {
284
                        if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0)
285
                                break;
286
 
287
                        dcache_add(inode, p, len, inode_number);
288
                }
289
                filp->f_pos += de_len;
290
                continue;
291
        }
292
        brelse(bh);
293
        return 0;
294
}
295
 
296
/*
297
 * Handle allocation of temporary space for name translation and
298
 * handling split directory entries.. The real work is done by
299
 * "do_isofs_readdir()".
300
 */
301
static int isofs_readdir(struct inode *inode, struct file *filp,
302
                void *dirent, filldir_t filldir)
303
{
304
        int result;
305
        char * tmpname;
306
        struct iso_directory_record * tmpde;
307
 
308
        if (!inode || !S_ISDIR(inode->i_mode))
309
                return -EBADF;
310
 
311
        tmpname = (char *) __get_free_page(GFP_KERNEL);
312
        if (!tmpname)
313
                return -ENOMEM;
314
        tmpde = (struct iso_directory_record *) (tmpname+1024);
315
 
316
        result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
317
 
318
        free_page((unsigned long) tmpname);
319
        return result;
320
}

powered by: WebSVN 2.1.0

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