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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [udf/] [directory.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * directory.c
3
 *
4
 * PURPOSE
5
 *      Directory related functions
6
 *
7
 * CONTACTS
8
 *      E-mail regarding any portion of the Linux UDF file system should be
9
 *      directed to the development team mailing list (run by majordomo):
10
 *              linux_udf@hpesjro.fc.hp.com
11
 *
12
 * COPYRIGHT
13
 *      This file is distributed under the terms of the GNU General Public
14
 *      License (GPL). Copies of the GPL can be obtained from:
15
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
16
 *      Each contributing author retains all rights to their own work.
17
 */
18
 
19
#include "udfdecl.h"
20
 
21
#include <linux/fs.h>
22
#include <linux/string.h>
23
 
24
uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
25
        lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
26
{
27
        int loffset = *offset;
28
        int block;
29
        uint8_t *ad;
30
        int remainder;
31
 
32
        *error = 0;
33
 
34
        ad = (uint8_t *)(*bh)->b_data + *offset;
35
        *offset += ad_size;
36
 
37
        if (!ad)
38
        {
39
                udf_release_data(*bh);
40
                *error = 1;
41
                return NULL;
42
        }
43
 
44
        if (*offset == dir->i_sb->s_blocksize)
45
        {
46
                udf_release_data(*bh);
47
                block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
48
                if (!block)
49
                        return NULL;
50
                if (!(*bh = udf_tread(dir->i_sb, block)))
51
                        return NULL;
52
        }
53
        else if (*offset > dir->i_sb->s_blocksize)
54
        {
55
                ad = tmpad;
56
 
57
                remainder = dir->i_sb->s_blocksize - loffset;
58
                memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder);
59
 
60
                udf_release_data(*bh);
61
                block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
62
                if (!block)
63
                        return NULL;
64
                if (!((*bh) = udf_tread(dir->i_sb, block)))
65
                        return NULL;
66
 
67
                memcpy((uint8_t *)ad + remainder, (*bh)->b_data, ad_size - remainder);
68
                *offset = ad_size - remainder;
69
        }
70
        return ad;
71
}
72
 
73
struct fileIdentDesc *
74
udf_fileident_read(struct inode *dir, loff_t *nf_pos,
75
        struct udf_fileident_bh *fibh,
76
        struct fileIdentDesc *cfi,
77
        lb_addr *bloc, uint32_t *extoffset,
78
        lb_addr *eloc, uint32_t *elen,
79
        uint32_t *offset, struct buffer_head **bh)
80
{
81
        struct fileIdentDesc *fi;
82
        int i, num, block;
83
        struct buffer_head * tmp, * bha[16];
84
 
85
        fibh->soffset = fibh->eoffset;
86
 
87
        if (fibh->eoffset == dir->i_sb->s_blocksize)
88
        {
89
                int lextoffset = *extoffset;
90
 
91
                if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
92
                        (EXT_RECORDED_ALLOCATED >> 30))
93
                {
94
                        return NULL;
95
                }
96
 
97
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
98
 
99
                (*offset) ++;
100
 
101
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
102
                        *offset = 0;
103
                else
104
                        *extoffset = lextoffset;
105
 
106
                udf_release_data(fibh->sbh);
107
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
108
                        return NULL;
109
                fibh->soffset = fibh->eoffset = 0;
110
 
111
                if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
112
                {
113
                        i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
114
                        if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits))
115
                                i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset;
116
                        for (num=0; i>0; i--)
117
                        {
118
                                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i);
119
                                tmp = udf_tgetblk(dir->i_sb, block);
120
                                if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
121
                                        bha[num++] = tmp;
122
                                else
123
                                        brelse(tmp);
124
                        }
125
                        if (num)
126
                        {
127
                                ll_rw_block(READA, num, bha);
128
                                for (i=0; i<num; i++)
129
                                        brelse(bha[i]);
130
                        }
131
                }
132
        }
133
        else if (fibh->sbh != fibh->ebh)
134
        {
135
                udf_release_data(fibh->sbh);
136
                fibh->sbh = fibh->ebh;
137
        }
138
 
139
        fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
140
                &(fibh->eoffset));
141
 
142
        if (!fi)
143
                return NULL;
144
 
145
        *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
146
 
147
        if (fibh->eoffset <= dir->i_sb->s_blocksize)
148
        {
149
                memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
150
        }
151
        else if (fibh->eoffset > dir->i_sb->s_blocksize)
152
        {
153
                int lextoffset = *extoffset;
154
 
155
                if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
156
                        (EXT_RECORDED_ALLOCATED >> 30))
157
                {
158
                        return NULL;
159
                }
160
 
161
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
162
 
163
                (*offset) ++;
164
 
165
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
166
                        *offset = 0;
167
                else
168
                        *extoffset = lextoffset;
169
 
170
                fibh->soffset -= dir->i_sb->s_blocksize;
171
                fibh->eoffset -= dir->i_sb->s_blocksize;
172
 
173
                if (!(fibh->ebh = udf_tread(dir->i_sb, block)))
174
                        return NULL;
175
 
176
                if (sizeof(struct fileIdentDesc) > - fibh->soffset)
177
                {
178
                        int fi_len;
179
 
180
                        memcpy((uint8_t *)cfi, (uint8_t *)fi, - fibh->soffset);
181
                        memcpy((uint8_t *)cfi - fibh->soffset, fibh->ebh->b_data,
182
                                sizeof(struct fileIdentDesc) + fibh->soffset);
183
 
184
                        fi_len = (sizeof(struct fileIdentDesc) + cfi->lengthFileIdent +
185
                                le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
186
 
187
                        *nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
188
                        fibh->eoffset = fibh->soffset + fi_len;
189
                }
190
                else
191
                {
192
                        memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
193
                }
194
        }
195
        return fi;
196
}
197
 
198
struct fileIdentDesc *
199
udf_get_fileident(void * buffer, int bufsize, int * offset)
200
{
201
        struct fileIdentDesc *fi;
202
        int lengthThisIdent;
203
        uint8_t * ptr;
204
        int padlen;
205
 
206
        if ( (!buffer) || (!offset) ) {
207
                udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, offset);
208
                return NULL;
209
        }
210
 
211
        ptr = buffer;
212
 
213
        if ( (*offset > 0) && (*offset < bufsize) ) {
214
                ptr += *offset;
215
        }
216
        fi=(struct fileIdentDesc *)ptr;
217
        if (le16_to_cpu(fi->descTag.tagIdent) != TAG_IDENT_FID)
218
        {
219
                udf_debug("0x%x != TAG_IDENT_FID\n",
220
                        le16_to_cpu(fi->descTag.tagIdent));
221
                udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
222
                        *offset, (unsigned long)sizeof(struct fileIdentDesc), bufsize);
223
                return NULL;
224
        }
225
        if ( (*offset + sizeof(struct fileIdentDesc)) > bufsize )
226
        {
227
                lengthThisIdent = sizeof(struct fileIdentDesc);
228
        }
229
        else
230
                lengthThisIdent = sizeof(struct fileIdentDesc) +
231
                        fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
232
 
233
        /* we need to figure padding, too! */
234
        padlen = lengthThisIdent % UDF_NAME_PAD;
235
        if (padlen)
236
                lengthThisIdent += (UDF_NAME_PAD - padlen);
237
        *offset = *offset + lengthThisIdent;
238
 
239
        return fi;
240
}
241
 
242
extent_ad *
243
udf_get_fileextent(void * buffer, int bufsize, int * offset)
244
{
245
        extent_ad * ext;
246
        struct fileEntry *fe;
247
        uint8_t * ptr;
248
 
249
        if ( (!buffer) || (!offset) )
250
        {
251
                printk(KERN_ERR "udf: udf_get_fileextent() invalidparms\n");
252
                return NULL;
253
        }
254
 
255
        fe = (struct fileEntry *)buffer;
256
 
257
        if ( le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_FE )
258
        {
259
                udf_debug("0x%x != TAG_IDENT_FE\n",
260
                        le16_to_cpu(fe->descTag.tagIdent));
261
                return NULL;
262
        }
263
 
264
        ptr=(uint8_t *)(fe->extendedAttr) + le32_to_cpu(fe->lengthExtendedAttr);
265
 
266
        if ( (*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs)) )
267
        {
268
                ptr += *offset;
269
        }
270
 
271
        ext = (extent_ad *)ptr;
272
 
273
        *offset = *offset + sizeof(extent_ad);
274
        return ext;
275
}
276
 
277
short_ad *
278
udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
279
{
280
        short_ad * sa;
281
        uint8_t * ptr;
282
 
283
        if ( (!buffer) || (!offset) )
284
        {
285
                printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
286
                return NULL;
287
        }
288
 
289
        ptr = (uint8_t *)buffer;
290
 
291
        if ( (*offset > 0) && (*offset < maxoffset) )
292
                ptr += *offset;
293
        else
294
                return NULL;
295
 
296
        if ((sa = (short_ad *)ptr)->extLength == 0)
297
                return NULL;
298
        else if (inc)
299
                (*offset) += sizeof(short_ad);
300
        return sa;
301
}
302
 
303
long_ad *
304
udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
305
{
306
        long_ad * la;
307
        uint8_t * ptr;
308
 
309
        if ( (!buffer) || !(offset) )
310
        {
311
                printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
312
                return NULL;
313
        }
314
 
315
        ptr = (uint8_t *)buffer;
316
 
317
        if ( (*offset > 0) && (*offset < maxoffset) )
318
                ptr += *offset;
319
        else
320
                return NULL;
321
 
322
        if ((la = (long_ad *)ptr)->extLength == 0)
323
                return NULL;
324
        else if (inc)
325
                (*offset) += sizeof(long_ad);
326
        return la;
327
}

powered by: WebSVN 2.1.0

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