~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/udf/misc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.