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)) {