Mercurial > mplayer.hg
comparison dvdread/dvd_udf.c @ 24050:1542693b2a30
Sync libdvdread with version 0.9.5 (cosmetic changes).
author | diego |
---|---|
date | Wed, 15 Aug 2007 11:57:30 +0000 |
parents | de28f9e8cb00 |
children | dcf5fe229d37 |
comparison
equal
deleted
inserted
replaced
24049:39b8ccb91251 | 24050:1542693b2a30 |
---|---|
1 /* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ | |
1 /* | 2 /* |
2 * This code is based on dvdudf by: | 3 * This code is based on dvdudf by: |
3 * Christian Wolff <scarabaeus@convergence.de>. | 4 * Christian Wolff <scarabaeus@convergence.de>. |
4 * | 5 * |
5 * Modifications by: | 6 * Modifications by: |
6 * Billy Biggs <vektor@dumbterm.net>. | 7 * Billy Biggs <vektor@dumbterm.net>. |
7 * Björn Englund <d4bjorn@dtek.chalmers.se>. | 8 * Björn Englund <d4bjorn@dtek.chalmers.se>. |
8 * | 9 * |
9 * Modified for use with MPlayer, changes contained in libdvdread_changes.diff. | |
10 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ | |
11 * $Id$ | |
12 * | |
13 * dvdudf: parse and read the UDF volume information of a DVD Video | 10 * dvdudf: parse and read the UDF volume information of a DVD Video |
14 * Copyright (C) 1999 Christian Wolff for convergence integrated media | 11 * Copyright (C) 1999 Christian Wolff for convergence integrated media |
15 * GmbH The author can be reached at scarabaeus@convergence.de, the | 12 * GmbH The author can be reached at scarabaeus@convergence.de, the |
16 * project's page is at http://linuxtv.org/dvd/ | 13 * project's page is at http://linuxtv.org/dvd/ |
17 * | 14 * |
15 * Modified for use with MPlayer, changes contained in libdvdread_changes.diff. | |
16 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ | |
17 * $Id$ | |
18 * | |
18 * This program is free software; you can redistribute it and/or modify | 19 * This program is free software; you can redistribute it and/or modify |
19 * it under the terms of the GNU General Public License as published by | 20 * it under the terms of the GNU General Public License as published by |
20 * the Free Software Foundation; either version 2 of the License, or (at | 21 * the Free Software Foundation; either version 2 of the License, or (at |
21 * your option) any later version. | 22 * your option) any later version. |
22 * | 23 * |
191 } | 192 } |
192 | 193 |
193 | 194 |
194 /* Private but located in/shared with dvd_reader.c */ | 195 /* Private but located in/shared with dvd_reader.c */ |
195 extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, | 196 extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, |
196 size_t block_count, unsigned char *data, | 197 size_t block_count, unsigned char *data, |
197 int encrypted ); | 198 int encrypted ); |
198 | 199 |
199 /** @internal | 200 /** @internal |
200 * Its required to either fail or deliver all the blocks asked for. | 201 * Its required to either fail or deliver all the blocks asked for. |
201 * | 202 * |
202 * @param data Pointer to a buffer where data is returned. This must be large | 203 * @param data Pointer to a buffer where data is returned. This must be large |
203 * enough to hold lb_number*2048 bytes. | 204 * enough to hold lb_number*2048 bytes. |
204 * It must be aligned to system specific (2048) logical blocks size when | 205 * It must be aligned to system specific (2048) logical blocks size when |
205 * reading from raw/O_DIRECT device. | 206 * reading from raw/O_DIRECT device. |
206 */ | 207 */ |
207 static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, | 208 static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, |
208 size_t block_count, unsigned char *data, | 209 size_t block_count, unsigned char *data, |
209 int encrypted ) | 210 int encrypted ) |
210 { | 211 { |
211 int ret; | 212 int ret; |
212 size_t count = block_count; | 213 size_t count = block_count; |
213 | 214 |
214 while(count > 0) { | 215 while(count > 0) { |
232 #ifndef NULL | 233 #ifndef NULL |
233 #define NULL ((void *)0) | 234 #define NULL ((void *)0) |
234 #endif | 235 #endif |
235 | 236 |
236 struct Partition { | 237 struct Partition { |
237 int valid; | 238 int valid; |
238 char VolumeDesc[128]; | 239 char VolumeDesc[128]; |
239 uint16_t Flags; | 240 uint16_t Flags; |
240 uint16_t Number; | 241 uint16_t Number; |
241 char Contents[32]; | 242 char Contents[32]; |
242 uint32_t AccessType; | 243 uint32_t AccessType; |
243 uint32_t Start; | 244 uint32_t Start; |
244 uint32_t Length; | 245 uint32_t Length; |
245 }; | 246 }; |
246 | 247 |
247 struct AD { | 248 struct AD { |
248 uint32_t Location; | 249 uint32_t Location; |
249 uint32_t Length; | 250 uint32_t Length; |
250 uint8_t Flags; | 251 uint8_t Flags; |
251 uint16_t Partition; | 252 uint16_t Partition; |
252 }; | 253 }; |
253 | 254 |
254 struct extent_ad { | 255 struct extent_ad { |
255 uint32_t location; | 256 uint32_t location; |
256 uint32_t length; | 257 uint32_t length; |
326 free(c); | 327 free(c); |
327 } | 328 } |
328 | 329 |
329 | 330 |
330 static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, | 331 static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, |
331 uint32_t nr, void *data) | 332 uint32_t nr, void *data) |
332 { | 333 { |
333 int n; | 334 int n; |
334 struct udf_cache *c; | 335 struct udf_cache *c; |
335 | 336 |
336 if(DVDUDFCacheLevel(device, -1) <= 0) { | 337 if(DVDUDFCacheLevel(device, -1) <= 0) { |
369 } | 370 } |
370 break; | 371 break; |
371 case LBUDFCache: | 372 case LBUDFCache: |
372 for(n = 0; n < c->lb_num; n++) { | 373 for(n = 0; n < c->lb_num; n++) { |
373 if(c->lbs[n].lb == nr) { | 374 if(c->lbs[n].lb == nr) { |
374 *(uint8_t **)data = c->lbs[n].data; | 375 *(uint8_t **)data = c->lbs[n].data; |
375 return 1; | 376 return 1; |
376 } | 377 } |
377 } | 378 } |
378 break; | 379 break; |
379 case MapCache: | 380 case MapCache: |
380 for(n = 0; n < c->map_num; n++) { | 381 for(n = 0; n < c->map_num; n++) { |
381 if(c->maps[n].lbn == nr) { | 382 if(c->maps[n].lbn == nr) { |
382 *(struct icbmap *)data = c->maps[n]; | 383 *(struct icbmap *)data = c->maps[n]; |
383 return 1; | 384 return 1; |
384 } | 385 } |
385 } | 386 } |
386 break; | 387 break; |
387 default: | 388 default: |
388 break; | 389 break; |
390 | 391 |
391 return 0; | 392 return 0; |
392 } | 393 } |
393 | 394 |
394 static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, | 395 static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, |
395 uint32_t nr, void *data) | 396 uint32_t nr, void *data) |
396 { | 397 { |
397 int n; | 398 int n; |
398 struct udf_cache *c; | 399 struct udf_cache *c; |
399 | 400 |
400 if(DVDUDFCacheLevel(device, -1) <= 0) { | 401 if(DVDUDFCacheLevel(device, -1) <= 0) { |
431 c->rooticb_valid = 1; | 432 c->rooticb_valid = 1; |
432 break; | 433 break; |
433 case LBUDFCache: | 434 case LBUDFCache: |
434 for(n = 0; n < c->lb_num; n++) { | 435 for(n = 0; n < c->lb_num; n++) { |
435 if(c->lbs[n].lb == nr) { | 436 if(c->lbs[n].lb == nr) { |
436 /* replace with new data */ | 437 /* replace with new data */ |
437 c->lbs[n].data = *(uint8_t **)data; | 438 c->lbs[n].data = *(uint8_t **)data; |
438 c->lbs[n].lb = nr; | 439 c->lbs[n].lb = nr; |
439 return 1; | 440 return 1; |
440 } | 441 } |
441 } | 442 } |
442 c->lb_num++; | 443 c->lb_num++; |
443 c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); | 444 c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); |
444 /* | 445 /* |
445 fprintf(stderr, "realloc lb: %d * %d = %d\n", | 446 fprintf(stderr, "realloc lb: %d * %d = %d\n", |
446 c->lb_num, sizeof(struct lbudf), | 447 c->lb_num, sizeof(struct lbudf), |
447 c->lb_num * sizeof(struct lbudf)); | 448 c->lb_num * sizeof(struct lbudf)); |
448 */ | 449 */ |
449 if(c->lbs == NULL) { | 450 if(c->lbs == NULL) { |
450 c->lb_num = 0; | 451 c->lb_num = 0; |
451 return 0; | 452 return 0; |
452 } | 453 } |
454 c->lbs[n].lb = nr; | 455 c->lbs[n].lb = nr; |
455 break; | 456 break; |
456 case MapCache: | 457 case MapCache: |
457 for(n = 0; n < c->map_num; n++) { | 458 for(n = 0; n < c->map_num; n++) { |
458 if(c->maps[n].lbn == nr) { | 459 if(c->maps[n].lbn == nr) { |
459 /* replace with new data */ | 460 /* replace with new data */ |
460 c->maps[n] = *(struct icbmap *)data; | 461 c->maps[n] = *(struct icbmap *)data; |
461 c->maps[n].lbn = nr; | 462 c->maps[n].lbn = nr; |
462 return 1; | 463 return 1; |
463 } | 464 } |
464 } | 465 } |
465 c->map_num++; | 466 c->map_num++; |
466 c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap)); | 467 c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap)); |
467 /* | 468 /* |
468 fprintf(stderr, "realloc maps: %d * %d = %d\n", | 469 fprintf(stderr, "realloc maps: %d * %d = %d\n", |
469 c->map_num, sizeof(struct icbmap), | 470 c->map_num, sizeof(struct icbmap), |
470 c->map_num * sizeof(struct icbmap)); | 471 c->map_num * sizeof(struct icbmap)); |
471 */ | 472 */ |
472 if(c->maps == NULL) { | 473 if(c->maps == NULL) { |
473 c->map_num = 0; | 474 c->map_num = 0; |
474 return 0; | 475 return 0; |
475 } | 476 } |
485 | 486 |
486 | 487 |
487 /* For direct data access, LSB first */ | 488 /* For direct data access, LSB first */ |
488 #define GETN1(p) ((uint8_t)data[p]) | 489 #define GETN1(p) ((uint8_t)data[p]) |
489 #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) | 490 #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) |
490 #define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ | 491 #define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ |
491 | ((uint32_t)data[(p) + 2] << 16)) | 492 | ((uint32_t)data[(p) + 2] << 16)) |
492 #define GETN4(p) ((uint32_t)data[p] \ | 493 #define GETN4(p) ((uint32_t)data[p] \ |
493 | ((uint32_t)data[(p) + 1] << 8) \ | 494 | ((uint32_t)data[(p) + 1] << 8) \ |
494 | ((uint32_t)data[(p) + 2] << 16) \ | 495 | ((uint32_t)data[(p) + 2] << 16) \ |
495 | ((uint32_t)data[(p) + 3] << 24)) | 496 | ((uint32_t)data[(p) + 3] << 24)) |
496 /* This is wrong with regard to endianess */ | 497 /* This is wrong with regard to endianess */ |
497 #define GETN(p, n, target) memcpy(target, &data[p], n) | 498 #define GETN(p, n, target) memcpy(target, &data[p], n) |
498 | 499 |
499 static int Unicodedecode( uint8_t *data, int len, char *target ) | 500 static int Unicodedecode( uint8_t *data, int len, char *target ) |
500 { | 501 { |
501 int p = 1, i = 0; | 502 int p = 1, i = 0; |
502 | 503 |
503 if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { | 504 if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { |
504 if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ | 505 if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ |
505 if( p < len ) { | 506 if( p < len ) { |
506 target[ i++ ] = data[ p++ ]; | 507 target[ i++ ] = data[ p++ ]; |
507 } | 508 } |
508 } while( p < len ); | 509 } while( p < len ); |
509 | 510 |
510 target[ i ] = '\0'; | 511 target[ i ] = '\0'; |
511 return 0; | 512 return 0; |
512 } | 513 } |
513 | 514 |
514 static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) | 515 static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) |
515 { | 516 { |
516 *TagID = GETN2(0); | 517 *TagID = GETN2(0); |
517 // TODO: check CRC 'n stuff | 518 // TODO: check CRC 'n stuff |
518 return 0; | 519 return 0; |
519 } | 520 } |
520 | 521 |
521 static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) | 522 static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) |
522 { | 523 { |
523 *Length = GETN4(0); | 524 *Length = GETN4(0); |
524 *Location = GETN4(4); | 525 *Location = GETN4(4); |
525 return 0; | 526 return 0; |
526 } | 527 } |
527 | 528 |
528 static int UDFShortAD( uint8_t *data, struct AD *ad, | 529 static int UDFShortAD( uint8_t *data, struct AD *ad, |
529 struct Partition *partition ) | 530 struct Partition *partition ) |
530 { | 531 { |
531 ad->Length = GETN4(0); | 532 ad->Length = GETN4(0); |
532 ad->Flags = ad->Length >> 30; | 533 ad->Flags = ad->Length >> 30; |
533 ad->Length &= 0x3FFFFFFF; | 534 ad->Length &= 0x3FFFFFFF; |
534 ad->Location = GETN4(4); | 535 ad->Location = GETN4(4); |
535 ad->Partition = partition->Number; // use number of current partition | 536 ad->Partition = partition->Number; // use number of current partition |
536 return 0; | 537 return 0; |
537 } | 538 } |
538 | 539 |
539 static int UDFLongAD( uint8_t *data, struct AD *ad ) | 540 static int UDFLongAD( uint8_t *data, struct AD *ad ) |
540 { | 541 { |
541 ad->Length = GETN4(0); | 542 ad->Length = GETN4(0); |
542 ad->Flags = ad->Length >> 30; | 543 ad->Flags = ad->Length >> 30; |
543 ad->Length &= 0x3FFFFFFF; | 544 ad->Length &= 0x3FFFFFFF; |
544 ad->Location = GETN4(4); | 545 ad->Location = GETN4(4); |
545 ad->Partition = GETN2(8); | 546 ad->Partition = GETN2(8); |
546 //GETN(10, 6, Use); | 547 //GETN(10, 6, Use); |
547 return 0; | 548 return 0; |
548 } | 549 } |
549 | 550 |
550 static int UDFExtAD( uint8_t *data, struct AD *ad ) | 551 static int UDFExtAD( uint8_t *data, struct AD *ad ) |
551 { | 552 { |
552 ad->Length = GETN4(0); | 553 ad->Length = GETN4(0); |
553 ad->Flags = ad->Length >> 30; | 554 ad->Flags = ad->Length >> 30; |
554 ad->Length &= 0x3FFFFFFF; | 555 ad->Length &= 0x3FFFFFFF; |
555 ad->Location = GETN4(12); | 556 ad->Location = GETN4(12); |
556 ad->Partition = GETN2(16); | 557 ad->Partition = GETN2(16); |
557 //GETN(10, 6, Use); | 558 //GETN(10, 6, Use); |
558 return 0; | 559 return 0; |
559 } | 560 } |
560 | 561 |
561 static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) | 562 static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) |
562 { | 563 { |
563 *FileType = GETN1(11); | 564 *FileType = GETN1(11); |
564 *Flags = GETN2(18); | 565 *Flags = GETN2(18); |
565 return 0; | 566 return 0; |
566 } | 567 } |
567 | 568 |
568 | 569 |
569 static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, | 570 static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, |
570 char *Contents, uint32_t *Start, uint32_t *Length ) | 571 char *Contents, uint32_t *Start, uint32_t *Length ) |
571 { | 572 { |
572 *Flags = GETN2(20); | 573 *Flags = GETN2(20); |
573 *Number = GETN2(22); | 574 *Number = GETN2(22); |
574 GETN(24, 32, Contents); | 575 GETN(24, 32, Contents); |
575 *Start = GETN4(188); | 576 *Start = GETN4(188); |
576 *Length = GETN4(192); | 577 *Length = GETN4(192); |
577 return 0; | 578 return 0; |
578 } | 579 } |
579 | 580 |
580 /** | 581 /** |
581 * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 | 582 * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 |
582 * on error. | 583 * on error. |
583 */ | 584 */ |
584 static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) | 585 static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) |
585 { | 586 { |
586 uint32_t lbsize, MT_L, N_PM; | 587 uint32_t lbsize, MT_L, N_PM; |
587 Unicodedecode(&data[84], 128, VolumeDescriptor); | 588 Unicodedecode(&data[84], 128, VolumeDescriptor); |
588 lbsize = GETN4(212); // should be 2048 | 589 lbsize = GETN4(212); // should be 2048 |
589 MT_L = GETN4(264); // should be 6 | 590 MT_L = GETN4(264); // should be 6 |
590 N_PM = GETN4(268); // should be 1 | 591 N_PM = GETN4(268); // should be 1 |
591 if (lbsize != DVD_VIDEO_LB_LEN) return 1; | 592 if (lbsize != DVD_VIDEO_LB_LEN) return 1; |
592 return 0; | 593 return 0; |
593 } | 594 } |
594 | 595 |
595 static int UDFFileEntry( uint8_t *data, uint8_t *FileType, | 596 static int UDFFileEntry( uint8_t *data, uint8_t *FileType, |
596 struct Partition *partition, struct AD *ad ) | 597 struct Partition *partition, struct AD *ad ) |
597 { | 598 { |
598 uint16_t flags; | 599 uint16_t flags; |
599 uint32_t L_EA, L_AD; | 600 uint32_t L_EA, L_AD; |
600 unsigned int p; | 601 unsigned int p; |
601 | 602 |
602 UDFICB( &data[ 16 ], FileType, &flags ); | 603 UDFICB( &data[ 16 ], FileType, &flags ); |
603 | 604 |
604 /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ | 605 /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ |
605 ad->Length = GETN4( 60 ); // Really 8 bytes a 56 | 606 ad->Length = GETN4( 60 ); // Really 8 bytes a 56 |
606 ad->Flags = 0; | 607 ad->Flags = 0; |
607 ad->Location = 0; // what should we put here? | 608 ad->Location = 0; // what should we put here? |
608 ad->Partition = partition->Number; // use number of current partition | 609 ad->Partition = partition->Number; // use number of current partition |
609 | 610 |
610 L_EA = GETN4( 168 ); | 611 L_EA = GETN4( 168 ); |
611 L_AD = GETN4( 172 ); | 612 L_AD = GETN4( 172 ); |
612 p = 176 + L_EA; | 613 p = 176 + L_EA; |
613 while( p < 176 + L_EA + L_AD ) { | 614 while( p < 176 + L_EA + L_AD ) { |
614 switch( flags & 0x0007 ) { | 615 switch( flags & 0x0007 ) { |
615 case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; | 616 case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; |
616 case 1: UDFLongAD( &data[ p ], ad ); p += 16; break; | 617 case 1: UDFLongAD( &data[ p ], ad ); p += 16; break; |
617 case 2: UDFExtAD( &data[ p ], ad ); p += 20; break; | 618 case 2: UDFExtAD( &data[ p ], ad ); p += 20; break; |
618 case 3: | 619 case 3: |
619 switch( L_AD ) { | 620 switch( L_AD ) { |
620 case 8: UDFShortAD( &data[ p ], ad, partition ); break; | 621 case 8: UDFShortAD( &data[ p ], ad, partition ); break; |
621 case 16: UDFLongAD( &data[ p ], ad ); break; | 622 case 16: UDFLongAD( &data[ p ], ad ); break; |
622 case 20: UDFExtAD( &data[ p ], ad ); break; | 623 case 20: UDFExtAD( &data[ p ], ad ); break; |
623 } | 624 } |
624 p += L_AD; | 625 p += L_AD; |
625 break; | 626 break; |
626 default: | 627 default: |
627 p += L_AD; break; | 628 p += L_AD; break; |
628 } | 629 } |
629 } | 630 } |
630 return 0; | 631 return 0; |
631 } | 632 } |
632 | 633 |
633 static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, | 634 static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, |
634 char *FileName, struct AD *FileICB ) | 635 char *FileName, struct AD *FileICB ) |
635 { | 636 { |
636 uint8_t L_FI; | 637 uint8_t L_FI; |
637 uint16_t L_IU; | 638 uint16_t L_IU; |
638 | 639 |
639 *FileCharacteristics = GETN1(18); | 640 *FileCharacteristics = GETN1(18); |
640 L_FI = GETN1(19); | 641 L_FI = GETN1(19); |
641 UDFLongAD(&data[20], FileICB); | 642 UDFLongAD(&data[20], FileICB); |
642 L_IU = GETN2(36); | 643 L_IU = GETN2(36); |
643 if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName); | 644 if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName); |
644 else FileName[0] = '\0'; | 645 else FileName[0] = '\0'; |
645 return 4 * ((38 + L_FI + L_IU + 3) / 4); | 646 return 4 * ((38 + L_FI + L_IU + 3) / 4); |
646 } | 647 } |
647 | 648 |
648 /** | 649 /** |
649 * Maps ICB to FileAD | 650 * Maps ICB to FileAD |
650 * ICB: Location of ICB of directory to scan | 651 * ICB: Location of ICB of directory to scan |
651 * FileType: Type of the file | 652 * FileType: Type of the file |
652 * File: Location of file the ICB is pointing to | 653 * File: Location of file the ICB is pointing to |
653 * return 1 on success, 0 on error; | 654 * return 1 on success, 0 on error; |
654 */ | 655 */ |
655 static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, | 656 static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, |
656 struct Partition *partition, struct AD *File ) | 657 struct Partition *partition, struct AD *File ) |
657 { | 658 { |
658 uint8_t *LogBlock; | 659 uint8_t *LogBlock; |
659 uint32_t lbnum; | 660 uint32_t lbnum; |
660 uint16_t TagID; | 661 uint16_t TagID; |
661 struct icbmap tmpmap; | 662 struct icbmap tmpmap; |
662 | 663 |
663 lbnum = partition->Start + ICB.Location; | 664 lbnum = partition->Start + ICB.Location; |
664 tmpmap.lbn = lbnum; | 665 tmpmap.lbn = lbnum; |
665 if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { | 666 if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { |
666 *FileType = tmpmap.filetype; | 667 *FileType = tmpmap.filetype; |
667 *File = tmpmap.file; | 668 *File = tmpmap.file; |
668 return 1; | 669 return 1; |
669 } | 670 } |
670 | 671 |
671 LogBlock = dvdalign_lbmalloc(device, 1); | 672 LogBlock = dvdalign_lbmalloc(device, 1); |
672 if(!LogBlock) { | 673 if(!LogBlock) { |
673 return 0; | 674 return 0; |
674 } | 675 } |
675 | 676 |
676 do { | 677 do { |
677 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { | 678 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { |
678 TagID = 0; | 679 TagID = 0; |
679 } else { | 680 } else { |
680 UDFDescriptor( LogBlock, &TagID ); | 681 UDFDescriptor( LogBlock, &TagID ); |
681 } | 682 } |
682 | 683 |
683 if( TagID == 261 ) { | 684 if( TagID == 261 ) { |
684 UDFFileEntry( LogBlock, FileType, partition, File ); | 685 UDFFileEntry( LogBlock, FileType, partition, File ); |
685 tmpmap.file = *File; | 686 tmpmap.file = *File; |
686 tmpmap.filetype = *FileType; | 687 tmpmap.filetype = *FileType; |
687 SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); | 688 SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); |
688 dvdalign_lbfree(device, LogBlock); | 689 dvdalign_lbfree(device, LogBlock); |
689 return 1; | 690 return 1; |
690 }; | 691 }; |
691 } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) | 692 } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) |
692 / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); | 693 / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); |
693 | 694 |
694 dvdalign_lbfree(device, LogBlock); | 695 dvdalign_lbfree(device, LogBlock); |
695 return 0; | 696 return 0; |
696 } | 697 } |
697 | 698 |
698 /** | 699 /** |
699 * Dir: Location of directory to scan | 700 * Dir: Location of directory to scan |
700 * FileName: Name of file to look for | 701 * FileName: Name of file to look for |
701 * FileICB: Location of ICB of the found file | 702 * FileICB: Location of ICB of the found file |
702 * return 1 on success, 0 on error; | 703 * return 1 on success, 0 on error; |
703 */ | 704 */ |
704 static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, | 705 static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, |
705 struct Partition *partition, struct AD *FileICB, | 706 struct Partition *partition, struct AD *FileICB, |
706 int cache_file_info) | 707 int cache_file_info) |
707 { | 708 { |
708 char filename[ MAX_UDF_FILE_NAME_LEN ]; | 709 char filename[ MAX_UDF_FILE_NAME_LEN ]; |
709 uint8_t *directory; | 710 uint8_t *directory; |
710 uint32_t lbnum; | 711 uint32_t lbnum; |
711 uint16_t TagID; | 712 uint16_t TagID; |
712 uint8_t filechar; | 713 uint8_t filechar; |
713 unsigned int p; | 714 unsigned int p; |
714 uint8_t *cached_dir = NULL; | 715 uint8_t *cached_dir = NULL; |
715 uint32_t dir_lba; | 716 uint32_t dir_lba; |
716 struct AD tmpICB; | 717 struct AD tmpICB; |
717 int found = 0; | 718 int found = 0; |
718 int in_cache = 0; | 719 int in_cache = 0; |
719 | 720 |
720 /* Scan dir for ICB of file */ | 721 /* Scan dir for ICB of file */ |
721 lbnum = partition->Start + Dir.Location; | 722 lbnum = partition->Start + Dir.Location; |
722 | 723 |
723 if(DVDUDFCacheLevel(device, -1) > 0) { | 724 if(DVDUDFCacheLevel(device, -1) > 0) { |
724 /* caching */ | 725 /* caching */ |
725 | 726 |
726 if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { | 727 if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { |
727 dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; | 728 dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; |
728 if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { | 729 if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { |
729 return 0; | 730 return 0; |
730 } | 731 } |
731 if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { | 732 if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { |
732 dvdalign_lbfree(device, cached_dir); | 733 dvdalign_lbfree(device, cached_dir); |
733 cached_dir = NULL; | 734 cached_dir = NULL; |
734 } | 735 } |
735 SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); | 736 SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); |
737 } else { | |
738 in_cache = 1; | |
739 } | |
740 | |
741 if(cached_dir == NULL) { | |
742 return 0; | |
743 } | |
744 | |
745 p = 0; | |
746 | |
747 while( p < Dir.Length ) { | |
748 UDFDescriptor( &cached_dir[ p ], &TagID ); | |
749 if( TagID == 257 ) { | |
750 p += UDFFileIdentifier( &cached_dir[ p ], &filechar, | |
751 filename, &tmpICB ); | |
752 if(cache_file_info && !in_cache) { | |
753 uint8_t tmpFiletype; | |
754 struct AD tmpFile; | |
755 | |
756 if( !strcasecmp( FileName, filename ) ) { | |
757 *FileICB = tmpICB; | |
758 found = 1; | |
759 | |
760 } | |
761 UDFMapICB(device, tmpICB, &tmpFiletype, | |
762 partition, &tmpFile); | |
763 } else { | |
764 if( !strcasecmp( FileName, filename ) ) { | |
765 *FileICB = tmpICB; | |
766 return 1; | |
767 } | |
768 } | |
736 } else { | 769 } else { |
737 in_cache = 1; | 770 if(cache_file_info && (!in_cache) && found) { |
738 } | 771 return 1; |
739 | |
740 if(cached_dir == NULL) { | |
741 return 0; | |
742 } | |
743 | |
744 p = 0; | |
745 | |
746 while( p < Dir.Length ) { | |
747 UDFDescriptor( &cached_dir[ p ], &TagID ); | |
748 if( TagID == 257 ) { | |
749 p += UDFFileIdentifier( &cached_dir[ p ], &filechar, | |
750 filename, &tmpICB ); | |
751 if(cache_file_info && !in_cache) { | |
752 uint8_t tmpFiletype; | |
753 struct AD tmpFile; | |
754 | |
755 if( !strcasecmp( FileName, filename ) ) { | |
756 *FileICB = tmpICB; | |
757 found = 1; | |
758 | |
759 } | |
760 UDFMapICB(device, tmpICB, &tmpFiletype, | |
761 partition, &tmpFile); | |
762 } else { | |
763 if( !strcasecmp( FileName, filename ) ) { | |
764 *FileICB = tmpICB; | |
765 return 1; | |
766 } | |
767 } | |
768 } else { | |
769 if(cache_file_info && (!in_cache) && found) { | |
770 return 1; | |
771 } | |
772 return 0; | |
773 } | 772 } |
774 } | 773 return 0; |
775 if(cache_file_info && (!in_cache) && found) { | 774 } |
776 return 1; | 775 } |
777 } | 776 if(cache_file_info && (!in_cache) && found) { |
778 return 0; | 777 return 1; |
779 } | 778 } |
779 return 0; | |
780 } | |
780 | 781 |
781 directory = dvdalign_lbmalloc(device, 2); | 782 directory = dvdalign_lbmalloc(device, 2); |
782 if(!directory) { | 783 if(!directory) { |
783 return 0; | 784 return 0; |
784 } | 785 } |
785 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { | 786 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { |
786 dvdalign_lbfree(device, directory); | 787 dvdalign_lbfree(device, directory); |
788 return 0; | |
789 } | |
790 | |
791 p = 0; | |
792 while( p < Dir.Length ) { | |
793 if( p > DVD_VIDEO_LB_LEN ) { | |
794 ++lbnum; | |
795 p -= DVD_VIDEO_LB_LEN; | |
796 Dir.Length -= DVD_VIDEO_LB_LEN; | |
797 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { | |
798 dvdalign_lbfree(device, directory); | |
787 return 0; | 799 return 0; |
788 } | 800 } |
789 | 801 } |
790 p = 0; | 802 UDFDescriptor( &directory[ p ], &TagID ); |
791 while( p < Dir.Length ) { | 803 if( TagID == 257 ) { |
792 if( p > DVD_VIDEO_LB_LEN ) { | 804 p += UDFFileIdentifier( &directory[ p ], &filechar, |
793 ++lbnum; | 805 filename, FileICB ); |
794 p -= DVD_VIDEO_LB_LEN; | 806 if( !strcasecmp( FileName, filename ) ) { |
795 Dir.Length -= DVD_VIDEO_LB_LEN; | |
796 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { | |
797 dvdalign_lbfree(device, directory); | 807 dvdalign_lbfree(device, directory); |
798 return 0; | 808 return 1; |
799 } | 809 } |
800 } | 810 } else { |
801 UDFDescriptor( &directory[ p ], &TagID ); | |
802 if( TagID == 257 ) { | |
803 p += UDFFileIdentifier( &directory[ p ], &filechar, | |
804 filename, FileICB ); | |
805 if( !strcasecmp( FileName, filename ) ) { | |
806 dvdalign_lbfree(device, directory); | |
807 return 1; | |
808 } | |
809 } else { | |
810 dvdalign_lbfree(device, directory); | 811 dvdalign_lbfree(device, directory); |
811 return 0; | 812 return 0; |
812 } | 813 } |
813 } | 814 } |
814 | 815 |
815 dvdalign_lbfree(device, directory); | 816 dvdalign_lbfree(device, directory); |
816 return 0; | 817 return 0; |
817 } | 818 } |
818 | 819 |
819 | 820 |
820 static int UDFGetAVDP( dvd_reader_t *device, | 821 static int UDFGetAVDP( dvd_reader_t *device, |
821 struct avdp_t *avdp) | 822 struct avdp_t *avdp) |
822 { | 823 { |
823 uint8_t *Anchor; | 824 uint8_t *Anchor; |
824 uint32_t lbnum, MVDS_location, MVDS_length; | 825 uint32_t lbnum, MVDS_location, MVDS_length; |
825 uint16_t TagID; | 826 uint16_t TagID; |
826 uint32_t lastsector; | 827 uint32_t lastsector; |
828 struct avdp_t; | 829 struct avdp_t; |
829 | 830 |
830 if(GetUDFCache(device, AVDPCache, 0, avdp)) { | 831 if(GetUDFCache(device, AVDPCache, 0, avdp)) { |
831 return 1; | 832 return 1; |
832 } | 833 } |
833 | 834 |
834 /* Find Anchor */ | 835 /* Find Anchor */ |
835 lastsector = 0; | 836 lastsector = 0; |
836 lbnum = 256; /* Try #1, prime anchor */ | 837 lbnum = 256; /* Try #1, prime anchor */ |
837 terminate = 0; | 838 terminate = 0; |
838 | 839 |
853 errno = EMEDIUMTYPE; | 854 errno = EMEDIUMTYPE; |
854 return 0; /* Final try failed */ | 855 return 0; /* Final try failed */ |
855 } | 856 } |
856 | 857 |
857 if( lastsector ) { | 858 if( lastsector ) { |
858 /* We already found the last sector. Try #3, alternative | 859 /* We already found the last sector. Try #3, alternative |
859 * backup anchor. If that fails, don't try again. | 860 * backup anchor. If that fails, don't try again. |
860 */ | 861 */ |
861 lbnum = lastsector; | 862 lbnum = lastsector; |
862 terminate = 1; | 863 terminate = 1; |
863 } else { | 864 } else { |
864 /* TODO: Find last sector of the disc (this is optional). */ | 865 /* TODO: Find last sector of the disc (this is optional). */ |
865 if( lastsector ) { | 866 if( lastsector ) { |
866 /* Try #2, backup anchor */ | 867 /* Try #2, backup anchor */ |
867 lbnum = lastsector - 256; | 868 lbnum = lastsector - 256; |
868 } else { | 869 } else { |
869 /* Unable to find last sector */ | 870 /* Unable to find last sector */ |
870 dvdalign_lbfree(device, Anchor); | 871 dvdalign_lbfree(device, Anchor); |
871 errno = EMEDIUMTYPE; | 872 errno = EMEDIUMTYPE; |
872 return 0; | 873 return 0; |
873 } | 874 } |
874 } | 875 } |
875 } else { | 876 } else { |
876 /* It's an anchor! We can leave */ | 877 /* It's an anchor! We can leave */ |
877 break; | 878 break; |
878 } | 879 } |
897 * Looks for partition on the disc. Returns 1 if partition found, 0 on error. | 898 * Looks for partition on the disc. Returns 1 if partition found, 0 on error. |
898 * partnum: Number of the partition, starting at 0. | 899 * partnum: Number of the partition, starting at 0. |
899 * part: structure to fill with the partition information | 900 * part: structure to fill with the partition information |
900 */ | 901 */ |
901 static int UDFFindPartition( dvd_reader_t *device, int partnum, | 902 static int UDFFindPartition( dvd_reader_t *device, int partnum, |
902 struct Partition *part ) | 903 struct Partition *part ) |
903 { | 904 { |
904 uint8_t *LogBlock; | 905 uint8_t *LogBlock; |
905 uint32_t lbnum, MVDS_location, MVDS_length; | 906 uint32_t lbnum, MVDS_location, MVDS_length; |
906 uint16_t TagID; | 907 uint16_t TagID; |
907 int i, volvalid; | 908 int i, volvalid; |
908 struct avdp_t avdp; | 909 struct avdp_t avdp; |
909 | 910 |
910 | 911 |
911 if(!UDFGetAVDP(device, &avdp)) { | 912 if(!UDFGetAVDP(device, &avdp)) { |
912 return 0; | 913 return 0; |
913 } | 914 } |
914 | 915 |
915 LogBlock = dvdalign_lbmalloc(device, 1); | 916 LogBlock = dvdalign_lbmalloc(device, 1); |
916 if(!LogBlock) { | 917 if(!LogBlock) { |
917 return 0; | 918 return 0; |
918 } | 919 } |
919 /* Main volume descriptor */ | 920 /* Main volume descriptor */ |
920 MVDS_location = avdp.mvds.location; | 921 MVDS_location = avdp.mvds.location; |
921 MVDS_length = avdp.mvds.length; | 922 MVDS_length = avdp.mvds.length; |
922 | 923 |
923 part->valid = 0; | 924 part->valid = 0; |
924 volvalid = 0; | 925 volvalid = 0; |
925 part->VolumeDesc[ 0 ] = '\0'; | 926 part->VolumeDesc[ 0 ] = '\0'; |
926 i = 1; | 927 i = 1; |
928 do { | |
929 /* Find Volume Descriptor */ | |
930 lbnum = MVDS_location; | |
927 do { | 931 do { |
928 /* Find Volume Descriptor */ | 932 |
929 lbnum = MVDS_location; | 933 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { |
930 do { | 934 TagID = 0; |
931 | 935 } else { |
932 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { | 936 UDFDescriptor( LogBlock, &TagID ); |
933 TagID = 0; | 937 } |
934 } else { | 938 |
935 UDFDescriptor( LogBlock, &TagID ); | 939 if( ( TagID == 5 ) && ( !part->valid ) ) { |
936 } | 940 /* Partition Descriptor */ |
937 | 941 UDFPartition( LogBlock, &part->Flags, &part->Number, |
938 if( ( TagID == 5 ) && ( !part->valid ) ) { | 942 part->Contents, &part->Start, &part->Length ); |
939 /* Partition Descriptor */ | 943 part->valid = ( partnum == part->Number ); |
940 UDFPartition( LogBlock, &part->Flags, &part->Number, | 944 } else if( ( TagID == 6 ) && ( !volvalid ) ) { |
941 part->Contents, &part->Start, &part->Length ); | 945 /* Logical Volume Descriptor */ |
942 part->valid = ( partnum == part->Number ); | 946 if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { |
943 } else if( ( TagID == 6 ) && ( !volvalid ) ) { | 947 /* TODO: sector size wrong! */ |
944 /* Logical Volume Descriptor */ | 948 } else { |
945 if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { | 949 volvalid = 1; |
946 /* TODO: sector size wrong! */ | |
947 } else { | |
948 volvalid = 1; | |
949 } | |
950 } | |
951 | |
952 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) | |
953 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) | |
954 && ( ( !part->valid ) || ( !volvalid ) ) ); | |
955 | |
956 if( ( !part->valid) || ( !volvalid ) ) { | |
957 /* Backup volume descriptor */ | |
958 MVDS_location = avdp.mvds.location; | |
959 MVDS_length = avdp.mvds.length; | |
960 } | 950 } |
961 } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); | 951 } |
952 | |
953 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) | |
954 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) | |
955 && ( ( !part->valid ) || ( !volvalid ) ) ); | |
956 | |
957 if( ( !part->valid) || ( !volvalid ) ) { | |
958 /* Backup volume descriptor */ | |
959 MVDS_location = avdp.mvds.location; | |
960 MVDS_length = avdp.mvds.length; | |
961 } | |
962 } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); | |
962 | 963 |
963 dvdalign_lbfree(device, LogBlock); | 964 dvdalign_lbfree(device, LogBlock); |
964 /* We only care for the partition, not the volume */ | 965 /* We only care for the partition, not the volume */ |
965 return part->valid; | 966 return part->valid; |
966 } | 967 } |
967 | 968 |
968 uint32_t UDFFindFile( dvd_reader_t *device, char *filename, | 969 uint32_t UDFFindFile( dvd_reader_t *device, char *filename, |
969 uint32_t *filesize ) | 970 uint32_t *filesize ) |
970 { | 971 { |
971 uint8_t *LogBlock; | 972 uint8_t *LogBlock; |
972 uint32_t lbnum; | 973 uint32_t lbnum; |
973 uint16_t TagID; | 974 uint16_t TagID; |
974 struct Partition partition; | 975 struct Partition partition; |
975 struct AD RootICB, File, ICB; | 976 struct AD RootICB, File, ICB; |
976 char tokenline[ MAX_UDF_FILE_NAME_LEN ]; | 977 char tokenline[ MAX_UDF_FILE_NAME_LEN ]; |
977 char *token; | 978 char *token; |
978 uint8_t filetype; | 979 uint8_t filetype; |
979 | 980 |
980 if(filesize) { | 981 if(filesize) { |
981 *filesize = 0; | 982 *filesize = 0; |
982 } | 983 } |
983 tokenline[0] = '\0'; | 984 tokenline[0] = '\0'; |
984 strcat( tokenline, filename ); | 985 strcat( tokenline, filename ); |
985 | 986 |
986 | 987 |
987 if(!(GetUDFCache(device, PartitionCache, 0, &partition) && | 988 if(!(GetUDFCache(device, PartitionCache, 0, &partition) && |
988 GetUDFCache(device, RootICBCache, 0, &RootICB))) { | 989 GetUDFCache(device, RootICBCache, 0, &RootICB))) { |
989 /* Find partition, 0 is the standard location for DVD Video.*/ | 990 /* Find partition, 0 is the standard location for DVD Video.*/ |
990 if( !UDFFindPartition( device, 0, &partition ) ) { | 991 if( !UDFFindPartition( device, 0, &partition ) ) { |
991 return 0; | 992 return 0; |
992 } | 993 } |
993 SetUDFCache(device, PartitionCache, 0, &partition); | 994 SetUDFCache(device, PartitionCache, 0, &partition); |
994 | 995 |
995 LogBlock = dvdalign_lbmalloc(device, 1); | 996 LogBlock = dvdalign_lbmalloc(device, 1); |
996 if(!LogBlock) { | 997 if(!LogBlock) { |
997 return 0; | 998 return 0; |
998 } | 999 } |
999 /* Find root dir ICB */ | 1000 /* Find root dir ICB */ |
1000 lbnum = partition.Start; | 1001 lbnum = partition.Start; |
1001 do { | 1002 do { |
1002 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { | 1003 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { |
1003 TagID = 0; | 1004 TagID = 0; |
1004 } else { | 1005 } else { |
1005 UDFDescriptor( LogBlock, &TagID ); | 1006 UDFDescriptor( LogBlock, &TagID ); |
1006 } | 1007 } |
1007 | 1008 |
1008 /* File Set Descriptor */ | 1009 /* File Set Descriptor */ |
1009 if( TagID == 256 ) { // File Set Descriptor | 1010 if( TagID == 256 ) { // File Set Descriptor |
1010 UDFLongAD( &LogBlock[ 400 ], &RootICB ); | 1011 UDFLongAD( &LogBlock[ 400 ], &RootICB ); |
1011 } | 1012 } |
1012 } while( ( lbnum < partition.Start + partition.Length ) | 1013 } while( ( lbnum < partition.Start + partition.Length ) |
1013 && ( TagID != 8 ) && ( TagID != 256 ) ); | 1014 && ( TagID != 8 ) && ( TagID != 256 ) ); |
1014 | 1015 |
1015 dvdalign_lbfree(device, LogBlock); | 1016 dvdalign_lbfree(device, LogBlock); |
1016 | 1017 |
1020 } | 1021 } |
1021 if( RootICB.Partition != 0 ) { | 1022 if( RootICB.Partition != 0 ) { |
1022 return 0; | 1023 return 0; |
1023 } | 1024 } |
1024 SetUDFCache(device, RootICBCache, 0, &RootICB); | 1025 SetUDFCache(device, RootICBCache, 0, &RootICB); |
1025 } | 1026 } |
1026 | 1027 |
1027 /* Find root dir */ | 1028 /* Find root dir */ |
1028 if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) { | 1029 if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) { |
1029 return 0; | 1030 return 0; |
1030 } | 1031 } |
1031 if( filetype != 4 ) { | 1032 if( filetype != 4 ) { |
1032 return 0; /* Root dir should be dir */ | 1033 return 0; /* Root dir should be dir */ |
1033 } | 1034 } |
1034 { | 1035 { |
1035 int cache_file_info = 0; | 1036 int cache_file_info = 0; |
1036 /* Tokenize filepath */ | 1037 /* Tokenize filepath */ |
1037 token = strtok(tokenline, "/"); | 1038 token = strtok(tokenline, "/"); |
1039 | |
1040 while( token != NULL ) { | |
1038 | 1041 |
1039 while( token != NULL ) { | 1042 if( !UDFScanDir( device, File, token, &partition, &ICB, |
1040 | 1043 cache_file_info)) { |
1041 if( !UDFScanDir( device, File, token, &partition, &ICB, | 1044 return 0; |
1042 cache_file_info)) { | 1045 } |
1043 return 0; | 1046 if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { |
1044 } | 1047 return 0; |
1045 if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { | 1048 } |
1046 return 0; | 1049 if(!strcmp(token, "VIDEO_TS")) { |
1047 } | 1050 cache_file_info = 1; |
1048 if(!strcmp(token, "VIDEO_TS")) { | 1051 } |
1049 cache_file_info = 1; | 1052 token = strtok( NULL, "/" ); |
1050 } | 1053 } |
1051 token = strtok( NULL, "/" ); | 1054 } |
1052 } | 1055 |
1053 } | 1056 /* Sanity check. */ |
1054 | |
1055 /* Sanity check. */ | |
1056 if( File.Partition != 0 ) { | 1057 if( File.Partition != 0 ) { |
1057 return 0; | 1058 return 0; |
1058 } | 1059 } |
1059 | 1060 |
1060 if(filesize) { | 1061 if(filesize) { |
1061 *filesize = File.Length; | 1062 *filesize = File.Length; |
1062 } | 1063 } |
1063 /* Hack to not return partition.Start for empty files. */ | 1064 /* Hack to not return partition.Start for empty files. */ |
1064 if( !File.Location ) { | 1065 if( !File.Location ) { |
1065 return 0; | 1066 return 0; |
1066 } else { | 1067 } else { |
1067 return partition.Start + File.Location; | 1068 return partition.Start + File.Location; |
1068 } | 1069 } |
1069 } | 1070 } |
1070 | 1071 |
1071 | 1072 |
1072 | 1073 |
1073 /** | 1074 /** |
1076 * id, tagid of descriptor | 1077 * id, tagid of descriptor |
1077 * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN) | 1078 * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN) |
1078 * and aligned for raw/O_DIRECT read. | 1079 * and aligned for raw/O_DIRECT read. |
1079 */ | 1080 */ |
1080 static int UDFGetDescriptor( dvd_reader_t *device, int id, | 1081 static int UDFGetDescriptor( dvd_reader_t *device, int id, |
1081 uint8_t *descriptor, int bufsize) | 1082 uint8_t *descriptor, int bufsize) |
1082 { | 1083 { |
1083 uint32_t lbnum, MVDS_location, MVDS_length; | 1084 uint32_t lbnum, MVDS_location, MVDS_length; |
1084 struct avdp_t avdp; | 1085 struct avdp_t avdp; |
1085 uint16_t TagID; | 1086 uint16_t TagID; |
1086 uint32_t lastsector; | 1087 uint32_t lastsector; |
1107 /* Find Descriptor */ | 1108 /* Find Descriptor */ |
1108 lbnum = MVDS_location; | 1109 lbnum = MVDS_location; |
1109 do { | 1110 do { |
1110 | 1111 |
1111 if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { | 1112 if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { |
1112 TagID = 0; | 1113 TagID = 0; |
1113 } else { | 1114 } else { |
1114 UDFDescriptor( descriptor, &TagID ); | 1115 UDFDescriptor( descriptor, &TagID ); |
1115 } | 1116 } |
1116 | 1117 |
1117 if( (TagID == id) && ( !desc_found ) ) { | 1118 if( (TagID == id) && ( !desc_found ) ) { |
1118 /* Descriptor */ | 1119 /* Descriptor */ |
1119 desc_found = 1; | 1120 desc_found = 1; |
1120 } | 1121 } |
1121 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) | 1122 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) |
1122 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) | 1123 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) |
1123 && ( !desc_found) ); | 1124 && ( !desc_found) ); |
1124 | 1125 |
1125 if( !desc_found ) { | 1126 if( !desc_found ) { |
1126 /* Backup volume descriptor */ | 1127 /* Backup volume descriptor */ |
1127 MVDS_location = avdp.rvds.location; | 1128 MVDS_location = avdp.rvds.location; |
1128 MVDS_length = avdp.rvds.length; | 1129 MVDS_length = avdp.rvds.length; |
1129 } | 1130 } |
1130 } while( i-- && ( !desc_found ) ); | 1131 } while( i-- && ( !desc_found ) ); |
1131 | 1132 |
1132 | 1133 |
1133 return desc_found; | 1134 return desc_found; |
1134 } | 1135 } |
1135 | 1136 |
1136 | 1137 |
1139 uint8_t *pvd_buf; | 1140 uint8_t *pvd_buf; |
1140 | 1141 |
1141 if(GetUDFCache(device, PVDCache, 0, pvd)) { | 1142 if(GetUDFCache(device, PVDCache, 0, pvd)) { |
1142 return 1; | 1143 return 1; |
1143 } | 1144 } |
1144 | 1145 |
1145 pvd_buf = dvdalign_lbmalloc(device, 1); | 1146 pvd_buf = dvdalign_lbmalloc(device, 1); |
1146 if(!pvd_buf) { | 1147 if(!pvd_buf) { |
1147 return 0; | 1148 return 0; |
1148 } | 1149 } |
1149 if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) { | 1150 if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) { |
1165 * volid, place to put the string | 1166 * volid, place to put the string |
1166 * volid_size, size of the buffer volid points to | 1167 * volid_size, size of the buffer volid points to |
1167 * returns the size of buffer needed for all data | 1168 * returns the size of buffer needed for all data |
1168 */ | 1169 */ |
1169 int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, | 1170 int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, |
1170 unsigned int volid_size) | 1171 unsigned int volid_size) |
1171 { | 1172 { |
1172 struct pvd_t pvd; | 1173 struct pvd_t pvd; |
1173 unsigned int volid_len; | 1174 unsigned int volid_len; |
1174 | 1175 |
1175 /* get primary volume descriptor */ | 1176 /* get primary volume descriptor */ |
1198 * the buffer should be >=128 bytes to store the whole volumesetidentifier | 1199 * the buffer should be >=128 bytes to store the whole volumesetidentifier |
1199 * returns the size of the available volsetid information (128) | 1200 * returns the size of the available volsetid information (128) |
1200 * or 0 on error | 1201 * or 0 on error |
1201 */ | 1202 */ |
1202 int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, | 1203 int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, |
1203 unsigned int volsetid_size) | 1204 unsigned int volsetid_size) |
1204 { | 1205 { |
1205 struct pvd_t pvd; | 1206 struct pvd_t pvd; |
1206 | 1207 |
1207 /* get primary volume descriptor */ | 1208 /* get primary volume descriptor */ |
1208 if(!UDFGetPVD(device, &pvd)) { | 1209 if(!UDFGetPVD(device, &pvd)) { |