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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [udf/] [misc.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
 * misc.c
3
 *
4
 * PURPOSE
5
 *      Miscellaneous routines for the OSTA-UDF(tm) filesystem.
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
 *  (C) 1998 Dave Boynton
19
 *  (C) 1998-2001 Ben Fennema
20
 *  (C) 1999-2000 Stelias Computing Inc
21
 *
22
 * HISTORY
23
 *
24
 *  04/19/99 blf  partial support for reading/writing specific EA's
25
 */
26
 
27
#include "udfdecl.h"
28
 
29
#include <linux/fs.h>
30
#include <linux/string.h>
31
#include <linux/udf_fs.h>
32
 
33
#include "udf_i.h"
34
#include "udf_sb.h"
35
 
36
uint32_t
37
udf64_low32(uint64_t indat)
38
{
39
        return indat & 0x00000000FFFFFFFFULL;
40
}
41
 
42
uint32_t
43
udf64_high32(uint64_t indat)
44
{
45
        return indat >> 32;
46
}
47
 
48
extern struct buffer_head *
49
udf_tgetblk(struct super_block *sb, int block)
50
{
51
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
52
                return sb_getblk(sb, udf_fixed_to_variable(block));
53
        else
54
                return sb_getblk(sb, block);
55
}
56
 
57
extern struct buffer_head *
58
udf_tread(struct super_block *sb, int block)
59
{
60
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
61
                return sb_bread(sb, udf_fixed_to_variable(block));
62
        else
63
                return sb_bread(sb, block);
64
}
65
 
66
extern struct genericFormat *
67
udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
68
        uint8_t loc, struct buffer_head **bh)
69
{
70
        uint8_t *ea = NULL, *ad = NULL;
71
        long_ad eaicb;
72
        int offset;
73
 
74
        *bh = udf_tread(inode->i_sb, inode->i_ino);
75
 
76
        if (UDF_I_EXTENDED_FE(inode) == 0)
77
        {
78
                struct fileEntry *fe;
79
 
80
                fe = (struct fileEntry *)(*bh)->b_data;
81
                eaicb = lela_to_cpu(fe->extendedAttrICB);
82
                offset = sizeof(struct fileEntry);
83
        }
84
        else
85
        {
86
                struct extendedFileEntry *efe;
87
 
88
                efe = (struct extendedFileEntry *)(*bh)->b_data;
89
                eaicb = lela_to_cpu(efe->extendedAttrICB);
90
                offset = sizeof(struct extendedFileEntry);
91
        }
92
 
93
        ea = &(*bh)->b_data[offset];
94
        if (UDF_I_LENEATTR(inode))
95
                offset += UDF_I_LENEATTR(inode);
96
        else
97
                size += sizeof(struct extendedAttrHeaderDesc);
98
 
99
        ad = &(*bh)->b_data[offset];
100
        if (UDF_I_LENALLOC(inode))
101
                offset += UDF_I_LENALLOC(inode);
102
 
103
        offset = inode->i_sb->s_blocksize - offset;
104
 
105
        /* TODO - Check for FreeEASpace */
106
 
107
        if (loc & 0x01 && offset >= size)
108
        {
109
                struct extendedAttrHeaderDesc *eahd;
110
                eahd = (struct extendedAttrHeaderDesc *)ea;
111
 
112
                if (UDF_I_LENALLOC(inode))
113
                {
114
                        memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
115
                }
116
 
117
                if (UDF_I_LENEATTR(inode))
118
                {
119
                        /* check checksum/crc */
120
                        if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
121
                                le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
122
                        {
123
                                udf_release_data(*bh);
124
                                return NULL;
125
                        }
126
                }
127
                else
128
                {
129
                        size -= sizeof(struct extendedAttrHeaderDesc);
130
                        UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
131
                        eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
132
                        eahd->descTag.descVersion = cpu_to_le16(2);
133
                        eahd->descTag.tagSerialNum = cpu_to_le16(1);
134
                        eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
135
                        eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
136
                        eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
137
                }
138
 
139
                offset = UDF_I_LENEATTR(inode);
140
                if (type < 2048)
141
                {
142
                        if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
143
                        {
144
                                uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
145
                                memmove(&ea[offset - aal + size],
146
                                        &ea[aal], offset - aal);
147
                                offset -= aal;
148
                                eahd->appAttrLocation = cpu_to_le32(aal + size);
149
                        }
150
                        if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
151
                        {
152
                                uint32_t ial = le32_to_cpu(eahd->impAttrLocation);
153
                                memmove(&ea[offset - ial + size],
154
                                        &ea[ial], offset - ial);
155
                                offset -= ial;
156
                                eahd->impAttrLocation = cpu_to_le32(ial + size);
157
                        }
158
                }
159
                else if (type < 65536)
160
                {
161
                        if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
162
                        {
163
                                uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
164
                                memmove(&ea[offset - aal + size],
165
                                        &ea[aal], offset - aal);
166
                                offset -= aal;
167
                                eahd->appAttrLocation = cpu_to_le32(aal + size);
168
                        }
169
                }
170
                /* rewrite CRC + checksum of eahd */
171
                UDF_I_LENEATTR(inode) += size;
172
                return (struct genericFormat *)&ea[offset];
173
        }
174
        if (loc & 0x02)
175
        {
176
        }
177
        udf_release_data(*bh);
178
        return NULL;
179
}
180
 
181
extern struct genericFormat *
182
udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
183
        struct buffer_head **bh)
184
{
185
        struct genericFormat *gaf;
186
        uint8_t *ea = NULL;
187
        long_ad eaicb;
188
        uint32_t offset;
189
 
190
        *bh = udf_tread(inode->i_sb, inode->i_ino);
191
 
192
        if (UDF_I_EXTENDED_FE(inode) == 0)
193
        {
194
                struct fileEntry *fe;
195
 
196
                fe = (struct fileEntry *)(*bh)->b_data;
197
                eaicb = lela_to_cpu(fe->extendedAttrICB);
198
                if (UDF_I_LENEATTR(inode))
199
                        ea = fe->extendedAttr;
200
        }
201
        else
202
        {
203
                struct extendedFileEntry *efe;
204
 
205
                efe = (struct extendedFileEntry *)(*bh)->b_data;
206
                eaicb = lela_to_cpu(efe->extendedAttrICB);
207
                if (UDF_I_LENEATTR(inode))
208
                        ea = efe->extendedAttr;
209
        }
210
 
211
        if (UDF_I_LENEATTR(inode))
212
        {
213
                struct extendedAttrHeaderDesc *eahd;
214
                eahd = (struct extendedAttrHeaderDesc *)ea;
215
 
216
                /* check checksum/crc */
217
                if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
218
                        le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
219
                {
220
                        udf_release_data(*bh);
221
                        return NULL;
222
                }
223
 
224
                if (type < 2048)
225
                        offset = sizeof(struct extendedAttrHeaderDesc);
226
                else if (type < 65536)
227
                        offset = le32_to_cpu(eahd->impAttrLocation);
228
                else
229
                        offset = le32_to_cpu(eahd->appAttrLocation);
230
 
231
                while (offset < UDF_I_LENEATTR(inode))
232
                {
233
                        gaf = (struct genericFormat *)&ea[offset];
234
                        if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
235
                                return gaf;
236
                        else
237
                                offset += le32_to_cpu(gaf->attrLength);
238
                }
239
        }
240
 
241
        udf_release_data(*bh);
242
        if (eaicb.extLength)
243
        {
244
                /* TODO */
245
        }
246
        return NULL;
247
}
248
 
249
/*
250
 * udf_read_tagged
251
 *
252
 * PURPOSE
253
 *      Read the first block of a tagged descriptor.
254
 *
255
 * HISTORY
256
 *      July 1, 1997 - Andrew E. Mileski
257
 *      Written, tested, and released.
258
 */
259
extern struct buffer_head *
260
udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident)
261
{
262
        tag *tag_p;
263
        struct buffer_head *bh = NULL;
264
        register uint8_t checksum;
265
        register int i;
266
 
267
        /* Read the block */
268
        if (block == 0xFFFFFFFF)
269
                return NULL;
270
 
271
        bh = udf_tread(sb, block);
272
        if (!bh)
273
        {
274
                udf_debug("block=%d, location=%d: read failed\n", block, location);
275
                return NULL;
276
        }
277
 
278
        tag_p = (tag *)(bh->b_data);
279
 
280
        *ident = le16_to_cpu(tag_p->tagIdent);
281
 
282
        if ( location != le32_to_cpu(tag_p->tagLocation) )
283
        {
284
                udf_debug("location mismatch block %u, tag %u != %u\n",
285
                        block, le32_to_cpu(tag_p->tagLocation), location);
286
                goto error_out;
287
        }
288
 
289
        /* Verify the tag checksum */
290
        checksum = 0U;
291
        for (i = 0; i < 4; i++)
292
                checksum += (uint8_t)(bh->b_data[i]);
293
        for (i = 5; i < 16; i++)
294
                checksum += (uint8_t)(bh->b_data[i]);
295
        if (checksum != tag_p->tagChecksum) {
296
                printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
297
                goto error_out;
298
        }
299
 
300
        /* Verify the tag version */
301
        if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
302
                le16_to_cpu(tag_p->descVersion) != 0x0003U)
303
        {
304
                udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
305
                        le16_to_cpu(tag_p->descVersion), block);
306
                goto error_out;
307
        }
308
 
309
        /* Verify the descriptor CRC */
310
        if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
311
                le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
312
                        le16_to_cpu(tag_p->descCRCLength), 0))
313
        {
314
                return bh;
315
        }
316
        udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
317
                block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
318
 
319
error_out:
320
        brelse(bh);
321
        return NULL;
322
}
323
 
324
extern struct buffer_head *
325
udf_read_ptagged(struct super_block *sb, lb_addr loc, uint32_t offset, uint16_t *ident)
326
{
327
        return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
328
                loc.logicalBlockNum + offset, ident);
329
}
330
 
331
void udf_release_data(struct buffer_head *bh)
332
{
333
        if (bh)
334
                brelse(bh);
335
}
336
 
337
void udf_update_tag(char *data, int length)
338
{
339
        tag *tptr = (tag *)data;
340
        int i;
341
 
342
        length -= sizeof(tag);
343
 
344
        tptr->tagChecksum = 0;
345
        tptr->descCRCLength = le16_to_cpu(length);
346
        tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
347
 
348
        for (i=0; i<16; i++)
349
                if (i != 4)
350
                        tptr->tagChecksum += (uint8_t)(data[i]);
351
}
352
 
353
void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
354
        uint32_t loc, int length)
355
{
356
        tag *tptr = (tag *)data;
357
        tptr->tagIdent = le16_to_cpu(ident);
358
        tptr->descVersion = le16_to_cpu(version);
359
        tptr->tagSerialNum = le16_to_cpu(snum);
360
        tptr->tagLocation = le32_to_cpu(loc);
361
        udf_update_tag(data, length);
362
}

powered by: WebSVN 2.1.0

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