1 /*
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@hootie.lvld.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-2000 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 #if defined(__linux__) && defined(__KERNEL__)
30
31 #include "udf_sb.h"
32 #include "udf_i.h"
33
34 #include <linux/fs.h>
35 #include <linux/string.h>
36 #include <linux/udf_fs.h>
37
38 #else
39
40 #include <sys/types.h>
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <string.h>
44
45 int udf_blocksize=0;
46 int udf_errno=0;
47
48 void
49 udf_setblocksize(int size)
50 {
51 udf_blocksize=size;
52 }
53 #endif
54
55 Uint32
56 udf64_low32(Uint64 indat)
57 {
58 return indat & 0x00000000FFFFFFFFULL;
59 }
60
61 Uint32
62 udf64_high32(Uint64 indat)
63 {
64 return indat >> 32;
65 }
66
67 #if defined(__linux__) && defined(__KERNEL__)
68
69 extern struct buffer_head *
70 udf_tread(struct super_block *sb, int block, int size)
71 {
72 if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
73 return bread(sb->s_dev, udf_fixed_to_variable(block), size);
74 else
75 return bread(sb->s_dev, block, size);
76 }
77
78 extern struct GenericAttrFormat *
79 udf_add_extendedattr(struct inode * inode, Uint32 size, Uint32 type,
80 Uint8 loc, struct buffer_head **bh)
81 {
82 Uint8 *ea = NULL, *ad = NULL;
83 long_ad eaicb;
84 int offset;
85
86 *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
87
88 if (UDF_I_EXTENDED_FE(inode) == 0)
89 {
90 struct FileEntry *fe;
91
92 fe = (struct FileEntry *)(*bh)->b_data;
93 eaicb = lela_to_cpu(fe->extendedAttrICB);
94 offset = sizeof(struct FileEntry);
95 }
96 else
97 {
98 struct ExtendedFileEntry *efe;
99
100 efe = (struct ExtendedFileEntry *)(*bh)->b_data;
101 eaicb = lela_to_cpu(efe->extendedAttrICB);
102 offset = sizeof(struct ExtendedFileEntry);
103 }
104
105 ea = &(*bh)->b_data[offset];
106 if (UDF_I_LENEATTR(inode))
107 offset += UDF_I_LENEATTR(inode);
108 else
109 size += sizeof(struct ExtendedAttrHeaderDesc);
110
111 ad = &(*bh)->b_data[offset];
112 if (UDF_I_LENALLOC(inode))
113 offset += UDF_I_LENALLOC(inode);
114
115 offset = inode->i_sb->s_blocksize - offset;
116
117 /* TODO - Check for FreeEASpace */
118
119 if (loc & 0x01 && offset >= size)
120 {
121 struct ExtendedAttrHeaderDesc *eahd;
122 eahd = (struct ExtendedAttrHeaderDesc *)ea;
123
124 if (UDF_I_LENALLOC(inode))
125 {
126 memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
127 }
128
129 if (UDF_I_LENEATTR(inode))
130 {
131 /* check checksum/crc */
132 if (le16_to_cpu(eahd->descTag.tagIdent) != TID_EXTENDED_ATTRE_HEADER_DESC ||
133 le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
134 {
135 udf_release_data(*bh);
136 return NULL;
137 }
138 }
139 else
140 {
141 size -= sizeof(struct ExtendedAttrHeaderDesc);
142 UDF_I_LENEATTR(inode) += sizeof(struct ExtendedAttrHeaderDesc);
143 eahd->descTag.tagIdent = cpu_to_le16(TID_EXTENDED_ATTRE_HEADER_DESC);
144 eahd->descTag.descVersion = cpu_to_le16(2);
145 eahd->descTag.tagSerialNum = cpu_to_le16(1);
146 eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
147 eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
148 eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
149 }
150
151 offset = UDF_I_LENEATTR(inode);
152 if (type < 2048)
153 {
154 if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
155 {
156 Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
157 memmove(&ea[offset - aal + size],
158 &ea[aal], offset - aal);
159 offset -= aal;
160 eahd->appAttrLocation = cpu_to_le32(aal + size);
161 }
162 if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
163 {
164 Uint32 ial = le32_to_cpu(eahd->impAttrLocation);
165 memmove(&ea[offset - ial + size],
166 &ea[ial], offset - ial);
167 offset -= ial;
168 eahd->impAttrLocation = cpu_to_le32(ial + size);
169 }
170 }
171 else if (type < 65536)
172 {
173 if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
174 {
175 Uint32 aal = le32_to_cpu(eahd->appAttrLocation);
176 memmove(&ea[offset - aal + size],
177 &ea[aal], offset - aal);
178 offset -= aal;
179 eahd->appAttrLocation = cpu_to_le32(aal + size);
180 }
181 }
182 /* rewrite CRC + checksum of eahd */
183 UDF_I_LENEATTR(inode) += size;
184 return (struct GenericAttrFormat *)&ea[offset];
185 }
186 if (loc & 0x02)
187 {
188 }
189 udf_release_data(*bh);
190 return NULL;
191 }
192
193 extern struct GenericAttrFormat *
194 udf_get_extendedattr(struct inode * inode, Uint32 type, Uint8 subtype,
195 struct buffer_head **bh)
196 {
197 struct GenericAttrFormat *gaf;
198 Uint8 *ea = NULL;
199 long_ad eaicb;
200 Uint32 offset;
201
202 *bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
203
204 if (UDF_I_EXTENDED_FE(inode) == 0)
205 {
206 struct FileEntry *fe;
207
208 fe = (struct FileEntry *)(*bh)->b_data;
209 eaicb = lela_to_cpu(fe->extendedAttrICB);
210 if (UDF_I_LENEATTR(inode))
211 ea = fe->extendedAttr;
212 }
213 else
214 {
215 struct ExtendedFileEntry *efe;
216
217 efe = (struct ExtendedFileEntry *)(*bh)->b_data;
218 eaicb = lela_to_cpu(efe->extendedAttrICB);
219 if (UDF_I_LENEATTR(inode))
220 ea = efe->extendedAttr;
221 }
222
223 if (UDF_I_LENEATTR(inode))
224 {
225 struct ExtendedAttrHeaderDesc *eahd;
226 eahd = (struct ExtendedAttrHeaderDesc *)ea;
227
228 /* check checksum/crc */
229 if (le16_to_cpu(eahd->descTag.tagIdent) != TID_EXTENDED_ATTRE_HEADER_DESC ||
230 le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
231 {
232 udf_release_data(*bh);
233 return NULL;
234 }
235
236 if (type < 2048)
237 offset = sizeof(struct ExtendedAttrHeaderDesc);
238 else if (type < 65536)
239 offset = le32_to_cpu(eahd->impAttrLocation);
240 else
241 offset = le32_to_cpu(eahd->appAttrLocation);
242
243 while (offset < UDF_I_LENEATTR(inode))
244 {
245 gaf = (struct GenericAttrFormat *)&ea[offset];
246 if (le32_to_cpu(gaf->attrType) == type && gaf->attrSubtype == subtype)
247 return gaf;
248 else
249 offset += le32_to_cpu(gaf->attrLength);
250 }
251 }
252
253 udf_release_data(*bh);
254 if (eaicb.extLength)
255 {
256 /* TODO */
257 }
258 return NULL;
259 }
260
261 extern struct buffer_head *
262 udf_read_untagged(struct super_block *sb, Uint32 block, Uint32 offset)
263 {
264 struct buffer_head *bh = NULL;
265
266 /* Read the block */
267 bh = udf_tread(sb, block+offset, sb->s_blocksize);
268 if (!bh)
269 {
270 printk(KERN_ERR "udf: udf_read_untagged(%p,%d,%d) failed\n",
271 sb, block, offset);
272 return NULL;
273 }
274 return bh;
275 }
276
277 /*
278 * udf_read_tagged
279 *
280 * PURPOSE
281 * Read the first block of a tagged descriptor.
282 *
283 * HISTORY
284 * July 1, 1997 - Andrew E. Mileski
285 * Written, tested, and released.
286 */
287 extern struct buffer_head *
288 udf_read_tagged(struct super_block *sb, Uint32 block, Uint32 location, Uint16 *ident)
289 {
290 tag *tag_p;
291 struct buffer_head *bh = NULL;
292 register Uint8 checksum;
293 register int i;
294
295 /* Read the block */
296 if (block == 0xFFFFFFFF)
297 return NULL;
298
299 bh = udf_tread(sb, block, sb->s_blocksize);
300 if (!bh)
301 {
302 udf_debug("block=%d, location=%d: read failed\n", block, location);
303 return NULL;
304 }
305
306 tag_p = (tag *)(bh->b_data);
307
308 *ident = le16_to_cpu(tag_p->tagIdent);
309
310 if ( location != le32_to_cpu(tag_p->tagLocation) )
311 {
312 udf_debug("location mismatch block %d, tag %d != %d\n",
313 block, le32_to_cpu(tag_p->tagLocation), location);
314 goto error_out;
315 }
316
317 /* Verify the tag checksum */
318 checksum = 0U;
319 for (i = 0; i < 4; i++)
320 checksum += (Uint8)(bh->b_data[i]);
321 for (i = 5; i < 16; i++)
322 checksum += (Uint8)(bh->b_data[i]);
323 if (checksum != tag_p->tagChecksum) {
324 printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
325 goto error_out;
326 }
327
328 /* Verify the tag version */
329 if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
330 le16_to_cpu(tag_p->descVersion) != 0x0003U)
331 {
332 udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
333 le16_to_cpu(tag_p->descVersion), block);
334 goto error_out;
335 }
336
337 /* Verify the descriptor CRC */
338 if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
339 le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
340 le16_to_cpu(tag_p->descCRCLength), 0))
341 {
342 return bh;
343 }
344 udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
345 block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
346
347 error_out:
348 brelse(bh);
349 return NULL;
350 }
351
352 extern struct buffer_head *
353 udf_read_ptagged(struct super_block *sb, lb_addr loc, Uint32 offset, Uint16 *ident)
354 {
355 return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
356 loc.logicalBlockNum + offset, ident);
357 }
358
359 void udf_release_data(struct buffer_head *bh)
360 {
361 if (bh)
362 brelse(bh);
363 }
364
365 #endif
366
367 void udf_update_tag(char *data, int length)
368 {
369 tag *tptr = (tag *)data;
370 int i;
371
372 length -= sizeof(tag);
373
374 tptr->tagChecksum = 0;
375 tptr->descCRCLength = le16_to_cpu(length);
376 tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
377
378 for (i=0; i<16; i++)
379 if (i != 4)
380 tptr->tagChecksum += (Uint8)(data[i]);
381 }
382
383 void udf_new_tag(char *data, Uint16 ident, Uint16 version, Uint16 snum,
384 Uint32 loc, int length)
385 {
386 tag *tptr = (tag *)data;
387 tptr->tagIdent = le16_to_cpu(ident);
388 tptr->descVersion = le16_to_cpu(version);
389 tptr->tagSerialNum = le16_to_cpu(snum);
390 tptr->tagLocation = le32_to_cpu(loc);
391 udf_update_tag(data, length);
392 }
393
394 #ifndef __KERNEL__
395 /*
396 * udf_read_tagged_data
397 *
398 * PURPOSE
399 * Read the first block of a tagged descriptor.
400 * Usable from user-land.
401 *
402 * HISTORY
403 * 10/4/98 dgb: written
404 */
405 int
406 udf_read_tagged_data(char *buffer, int size, int fd, int block, int offset)
407 {
408 tag *tag_p;
409 register Uint8 checksum;
410 register int i;
411 unsigned long offs;
412
413 if (!buffer)
414 {
415 udf_errno = 1;
416 return -1;
417 }
418
419 if ( !udf_blocksize )
420 {
421 udf_errno = 2;
422 return -1;
423 }
424
425 if ( size < udf_blocksize )
426 {
427 udf_errno=3;
428 return -1;
429 }
430 udf_errno=0;
431
432 offs=(long)block * udf_blocksize;
433 if ( lseek(fd, offs, SEEK_SET) != offs ) {
434 udf_errno=4;
435 return -1;
436 }
437
438 i=read(fd, buffer, udf_blocksize);
439 if ( i < udf_blocksize ) {
440 udf_errno=5;
441 return -1;
442 }
443
444 tag_p = (tag *)(buffer);
445
446 /* Verify the tag location */
447 if ((block-offset) != tag_p->tagLocation) {
448 #ifdef __KERNEL__
449 printk(KERN_ERR "udf: location mismatch block %d, tag %d\n",
450 block, tag_p->tagLocation);
451 #else
452 udf_errno=6;
453 #endif
454 goto error_out;
455 }
456
457 /* Verify the tag checksum */
458 checksum = 0U;
459 for (i = 0; i < 4; i++)
460 checksum += (Uint8)(buffer[i]);
461 for (i = 5; i < 16; i++)
462 checksum += (Uint8)(buffer[i]);
463 if (checksum != tag_p->tagChecksum) {
464 #ifdef __KERNEL__
465 printk(KERN_ERR "udf: tag checksum failed\n");
466 #else
467 udf_errno=7;
468 #endif
469 goto error_out;
470 }
471
472 /* Verify the tag version */
473 if (tag_p->descVersion != 0x0002U) {
474 #ifdef __KERNEL__
475 printk(KERN_ERR "udf: tag version 0x%04x != 0x0002U\n",
476 tag_p->descVersion);
477 #else
478 udf_errno=8;
479 #endif
480 goto error_out;
481 }
482
483 /* Verify the descriptor CRC */
484 if (tag_p->descCRC == udf_crc(buffer + 16, tag_p->descCRCLength, 0)) {
485 udf_errno=0;
486 return 0;
487 }
488 #ifdef __KERNEL__
489 printk(KERN_ERR "udf: crc failure in udf_read_tagged\n");
490 #else
491 udf_errno=9;
492 #endif
493
494 error_out:
495 return -1;
496 }
497 #endif
498
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.