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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [isofs/] [dir.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  linux/fs/isofs/dir.c
3
 *
4
 *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO 9660 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/smp_lock.h>
14
#include "isofs.h"
15
 
16
int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
17
{
18
        char * old = de->name;
19
        int len = de->name_len[0];
20
        int i;
21
 
22
        for (i = 0; i < len; i++) {
23
                unsigned char c = old[i];
24
                if (!c)
25
                        break;
26
 
27
                if (c >= 'A' && c <= 'Z')
28
                        c |= 0x20;      /* lower case */
29
 
30
                /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
31
                if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
32
                        break;
33
 
34
                /* Drop trailing ';1' */
35
                if (c == ';' && i == len - 2 && old[i + 1] == '1')
36
                        break;
37
 
38
                /* Convert remaining ';' to '.' */
39
                /* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
40
                if (c == ';' || c == '/')
41
                        c = '.';
42
 
43
                new[i] = c;
44
        }
45
        return i;
46
}
47
 
48
/* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
49
int get_acorn_filename(struct iso_directory_record *de,
50
                            char *retname, struct inode *inode)
51
{
52
        int std;
53
        unsigned char *chr;
54
        int retnamlen = isofs_name_translate(de, retname, inode);
55
 
56
        if (retnamlen == 0)
57
                return 0;
58
        std = sizeof(struct iso_directory_record) + de->name_len[0];
59
        if (std & 1)
60
                std++;
61
        if ((*((unsigned char *) de) - std) != 32)
62
                return retnamlen;
63
        chr = ((unsigned char *) de) + std;
64
        if (strncmp(chr, "ARCHIMEDES", 10))
65
                return retnamlen;
66
        if ((*retname == '_') && ((chr[19] & 1) == 1))
67
                *retname = '!';
68
        if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
69
                && ((chr[12] & 0xf0) == 0xf0)) {
70
                retname[retnamlen] = ',';
71
                sprintf(retname+retnamlen+1, "%3.3x",
72
                        ((chr[12] & 0xf) << 8) | chr[11]);
73
                retnamlen += 4;
74
        }
75
        return retnamlen;
76
}
77
 
78
/*
79
 * This should _really_ be cleaned up some day..
80
 */
81
static int do_isofs_readdir(struct inode *inode, struct file *filp,
82
                void *dirent, filldir_t filldir,
83
                char *tmpname, struct iso_directory_record *tmpde)
84
{
85
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
86
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
87
        unsigned long block, offset, block_saved, offset_saved;
88
        unsigned long inode_number = 0;  /* Quiet GCC */
89
        struct buffer_head *bh = NULL;
90
        int len;
91
        int map;
92
        int first_de = 1;
93
        char *p = NULL;         /* Quiet GCC */
94
        struct iso_directory_record *de;
95
        struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
96
 
97
        offset = filp->f_pos & (bufsize - 1);
98
        block = filp->f_pos >> bufbits;
99
 
100
        while (filp->f_pos < inode->i_size) {
101
                int de_len;
102
 
103
                if (!bh) {
104
                        bh = isofs_bread(inode, block);
105
                        if (!bh)
106
                                return 0;
107
                }
108
 
109
                de = (struct iso_directory_record *) (bh->b_data + offset);
110
 
111
                de_len = *(unsigned char *) de;
112
 
113
                /*
114
                 * If the length byte is zero, we should move on to the next
115
                 * CDROM sector.  If we are at the end of the directory, we
116
                 * kick out of the while loop.
117
                 */
118
 
119
                if (de_len == 0) {
120
                        brelse(bh);
121
                        bh = NULL;
122
                        filp->f_pos = (filp->f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
123
                        block = filp->f_pos >> bufbits;
124
                        offset = 0;
125
                        continue;
126
                }
127
 
128
                block_saved = block;
129
                offset_saved = offset;
130
                offset += de_len;
131
 
132
                /* Make sure we have a full directory entry */
133
                if (offset >= bufsize) {
134
                        int slop = bufsize - offset + de_len;
135
                        memcpy(tmpde, de, slop);
136
                        offset &= bufsize - 1;
137
                        block++;
138
                        brelse(bh);
139
                        bh = NULL;
140
                        if (offset) {
141
                                bh = isofs_bread(inode, block);
142
                                if (!bh)
143
                                        return 0;
144
                                memcpy((void *) tmpde + slop, bh->b_data, offset);
145
                        }
146
                        de = tmpde;
147
                }
148
 
149
                if (first_de) {
150
                        isofs_normalize_block_and_offset(de,
151
                                                        &block_saved,
152
                                                        &offset_saved);
153
                        inode_number = isofs_get_ino(block_saved,
154
                                                        offset_saved, bufbits);
155
                }
156
 
157
                if (de->flags[-sbi->s_high_sierra] & 0x80) {
158
                        first_de = 0;
159
                        filp->f_pos += de_len;
160
                        continue;
161
                }
162
                first_de = 1;
163
 
164
                /* Handle the case of the '.' directory */
165
                if (de->name_len[0] == 1 && de->name[0] == 0) {
166
                        if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
167
                                break;
168
                        filp->f_pos += de_len;
169
                        continue;
170
                }
171
 
172
                len = 0;
173
 
174
                /* Handle the case of the '..' directory */
175
                if (de->name_len[0] == 1 && de->name[0] == 1) {
176
                        inode_number = parent_ino(filp->f_path.dentry);
177
                        if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
178
                                break;
179
                        filp->f_pos += de_len;
180
                        continue;
181
                }
182
 
183
                /* Handle everything else.  Do name translation if there
184
                   is no Rock Ridge NM field. */
185
 
186
                /*
187
                 * Do not report hidden files if so instructed, or associated
188
                 * files unless instructed to do so
189
                 */
190
                if ((sbi->s_hide == 'y' &&
191
                                (de->flags[-sbi->s_high_sierra] & 1)) ||
192
                                (sbi->s_showassoc =='n' &&
193
                                (de->flags[-sbi->s_high_sierra] & 4))) {
194
                        filp->f_pos += de_len;
195
                        continue;
196
                }
197
 
198
                map = 1;
199
                if (sbi->s_rock) {
200
                        len = get_rock_ridge_filename(de, tmpname, inode);
201
                        if (len != 0) {          /* may be -1 */
202
                                p = tmpname;
203
                                map = 0;
204
                        }
205
                }
206
                if (map) {
207
#ifdef CONFIG_JOLIET
208
                        if (sbi->s_joliet_level) {
209
                                len = get_joliet_filename(de, tmpname, inode);
210
                                p = tmpname;
211
                        } else
212
#endif
213
                        if (sbi->s_mapping == 'a') {
214
                                len = get_acorn_filename(de, tmpname, inode);
215
                                p = tmpname;
216
                        } else
217
                        if (sbi->s_mapping == 'n') {
218
                                len = isofs_name_translate(de, tmpname, inode);
219
                                p = tmpname;
220
                        } else {
221
                                p = de->name;
222
                                len = de->name_len[0];
223
                        }
224
                }
225
                if (len > 0) {
226
                        if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0)
227
                                break;
228
                }
229
                filp->f_pos += de_len;
230
 
231
                continue;
232
        }
233
        if (bh)
234
                brelse(bh);
235
        return 0;
236
}
237
 
238
/*
239
 * Handle allocation of temporary space for name translation and
240
 * handling split directory entries.. The real work is done by
241
 * "do_isofs_readdir()".
242
 */
243
static int isofs_readdir(struct file *filp,
244
                void *dirent, filldir_t filldir)
245
{
246
        int result;
247
        char *tmpname;
248
        struct iso_directory_record *tmpde;
249
        struct inode *inode = filp->f_path.dentry->d_inode;
250
 
251
        tmpname = (char *)__get_free_page(GFP_KERNEL);
252
        if (tmpname == NULL)
253
                return -ENOMEM;
254
 
255
        lock_kernel();
256
        tmpde = (struct iso_directory_record *) (tmpname+1024);
257
 
258
        result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
259
 
260
        free_page((unsigned long) tmpname);
261
        unlock_kernel();
262
        return result;
263
}
264
 
265
const struct file_operations isofs_dir_operations =
266
{
267
        .read = generic_read_dir,
268
        .readdir = isofs_readdir,
269
};
270
 
271
/*
272
 * directories can handle most operations...
273
 */
274
const struct inode_operations isofs_dir_inode_operations =
275
{
276
        .lookup = isofs_lookup,
277
};
278
 
279
 

powered by: WebSVN 2.1.0

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