Example #1
0
/**
 * Maps ICB to FileAD
 * ICB: Location of ICB of directory to scan
 * FileType: Type of the file
 * File: Location of file the ICB is pointing to
 * return 1 on success, 0 on error;
 */
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
                      struct Partition *partition, struct AD *File )
{
  uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum;
  uint16_t TagID;
  struct icbmap tmpmap;

  lbnum = partition->Start + ICB.Location;
  tmpmap.lbn = lbnum;
  if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) {
    *FileType = tmpmap.filetype;
    memcpy(File, &tmpmap.file, sizeof(tmpmap.file));
    return 1;
  }

  do {
    if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 )
      TagID = 0;
    else
      UDFDescriptor( LogBlock, &TagID );

    if( TagID == 261 ) {
      UDFFileEntry( LogBlock, FileType, partition, File );
      memcpy(&tmpmap.file, File, sizeof(tmpmap.file));
      tmpmap.filetype = *FileType;
      SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
      return 1;
    };
  } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 )
             / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) );

  return 0;
}
Example #2
0
/**
 * Looks for partition on the disc.  Returns 1 if partition found, 0 on error.
 *   partnum: Number of the partition, starting at 0.
 *   part: structure to fill with the partition information
 */
static int UDFFindPartition( dvd_reader_t *device, int partnum,
                             struct Partition *part )
{
  uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum, MVDS_location, MVDS_length;
  uint16_t TagID;
  int i, volvalid;
  struct avdp_t avdp;

  if(!UDFGetAVDP(device, &avdp))
    return 0;

  /* Main volume descriptor */
  MVDS_location = avdp.mvds.location;
  MVDS_length = avdp.mvds.length;

  part->valid = 0;
  volvalid = 0;
  part->VolumeDesc[ 0 ] = '\0';
  i = 1;
  do {
    /* Find Volume Descriptor */
    lbnum = MVDS_location;
    do {

      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 )
        TagID = 0;
      else
        UDFDescriptor( LogBlock, &TagID );

      if( ( TagID == 5 ) && ( !part->valid ) ) {
        /* Partition Descriptor */
        UDFPartition( LogBlock, &part->Flags, &part->Number,
                      part->Contents, &part->Start, &part->Length );
        part->valid = ( partnum == part->Number );
      } else if( ( TagID == 6 ) && ( !volvalid ) ) {
        /* Logical Volume Descriptor */
        if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) {
          /* TODO: sector size wrong! */
        } else
          volvalid = 1;
      }

    } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
               / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
             && ( ( !part->valid ) || ( !volvalid ) ) );

    if( ( !part->valid) || ( !volvalid ) ) {
      /* Backup volume descriptor */
      MVDS_location = avdp.mvds.location;
      MVDS_length = avdp.mvds.length;
    }
  } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );

  /* We only care for the partition, not the volume */
  return part->valid;
}
Example #3
0
/**
 * Gets a Descriptor .
 * Returns 1 if descriptor found, 0 on error.
 * id, tagid of descriptor
 * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN)
 * and aligned for raw/O_DIRECT read.
 */
static int UDFGetDescriptor( dvd_reader_t *device, int id,
                             uint8_t *descriptor, int bufsize) 
{
  uint32_t lbnum, MVDS_location, MVDS_length;
  struct avdp_t avdp;
  uint16_t TagID;
  uint32_t lastsector;
  int i, terminate;
  int desc_found = 0;
  /* Find Anchor */
  lastsector = 0;
  lbnum = 256;   /* Try #1, prime anchor */
  terminate = 0;
  if(bufsize < DVD_VIDEO_LB_LEN) {
    return 0;
  }
  
  if(!UDFGetAVDP(device, &avdp)) {
    return 0;
  }

  /* Main volume descriptor */
  MVDS_location = avdp.mvds.location;
  MVDS_length = avdp.mvds.length;
  
  i = 1;
  do {
    /* Find  Descriptor */
    lbnum = MVDS_location;
    do {
      
      if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) {
        TagID = 0;
      } else {
        UDFDescriptor( descriptor, &TagID );
      }
      
      if( (TagID == id) && ( !desc_found ) ) {
        /* Descriptor */
        desc_found = 1;
      }
    } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
               / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
             && ( !desc_found) );
    
    if( !desc_found ) {
      /* Backup volume descriptor */
      MVDS_location = avdp.rvds.location;
      MVDS_length = avdp.rvds.length;
    }
  } while( i-- && ( !desc_found )  );

  
  return desc_found;
}
Example #4
0
/**
 * Maps ICB to FileAD
 * ICB: Location of ICB of directory to scan
 * FileType: Type of the file
 * File: Location of file the ICB is pointing to
 * return 1 on success, 0 on error;
 */
static int UDFMapICB( UDF_DATA *device, struct AD ICB, uint8_t *FileType,
                      struct Partition *partition, struct AD *File )
{
  uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum;
  uint16_t TagID;
  struct icbmap tmpmap;


  //lbnum = partition->Start + ICB.Location;
  lbnum = UDFGetBlock(partition, ICB.Partition, ICB.Location);
  //printf("lbnum: %d\n", lbnum);
  tmpmap.lbn = lbnum;
  if(GetBDUDFCache(device, MapCache, lbnum, &tmpmap)) {
    *FileType = tmpmap.filetype;
    memcpy(File, &tmpmap.file, sizeof(tmpmap.file));
    return 1;
  }

  do {
    if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
		return 0;
      TagID = 0;
	} else
      UDFDescriptor( LogBlock, &TagID );

	//printf("icb tagid: %d\n", TagID);
    if( TagID == 261 ) {
      UDFFileEntry( LogBlock, FileType, partition, File );
      memcpy(&tmpmap.file, File, sizeof(tmpmap.file));
      tmpmap.filetype = *FileType;
      SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
      return 1;
    }
	else if ( TagID == 266 )
	{
      UDFExtFileEntry( LogBlock, FileType, partition, File );
	  //printf("in file: part: %u, block: %u\n", File->Partition, File->Location);
      memcpy(&tmpmap.file, File, sizeof(tmpmap.file));
      tmpmap.filetype = *FileType;
      SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
      return 1;
	}
  } while( ( lbnum <= lbnum + ( ICB.Length - 1 )
             / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) );

  return 0;
}
Example #5
0
/**
 * Maps ICB to FileAD
 * ICB: Location of ICB of directory to scan
 * FileType: Type of the file
 * File: Location of file the ICB is pointing to
 * return 1 on success, 0 on error;
 */
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
                      struct Partition *partition, struct AD *File ) 
{
  uint8_t *LogBlock;
  uint32_t lbnum;
  uint16_t TagID;
  struct icbmap tmpmap;

  lbnum = partition->Start + ICB.Location;
  tmpmap.lbn = lbnum;
  if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) {
    *FileType = tmpmap.filetype;
    *File = tmpmap.file;
    return 1;
  }

  LogBlock = dvdalign_lbmalloc(device, 1);
  if(!LogBlock) {
    return 0;
  }
    
  do {
    if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
      TagID = 0;
    } else {
      UDFDescriptor( LogBlock, &TagID );
    }

    if( TagID == 261 ) {
      UDFFileEntry( LogBlock, FileType, partition, File );
      tmpmap.file = *File;
      tmpmap.filetype = *FileType;
      SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
      dvdalign_lbfree(device, LogBlock);
      return 1;
    };
  } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 )
             / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) );

  dvdalign_lbfree(device, LogBlock);
  return 0;
}
Example #6
0
uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
                      uint32_t *filesize )
{
  uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum;
  uint16_t TagID;
  struct Partition partition;
  struct AD RootICB, File, ICB;
  char tokenline[ MAX_UDF_FILE_NAME_LEN ];
  char *token;
  uint8_t filetype;

  *filesize = 0;
  tokenline[0] = '\0';
  strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1);
  memset(&ICB, 0, sizeof(ICB));

  if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
       GetUDFCache(device, RootICBCache, 0, &RootICB))) {
    /* Find partition, 0 is the standard location for DVD Video.*/
    if( !UDFFindPartition( device, 0, &partition ) ) return 0;
    SetUDFCache(device, PartitionCache, 0, &partition);

    /* Find root dir ICB */
    lbnum = partition.Start;
    do {
      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 )
        TagID = 0;
      else
        UDFDescriptor( LogBlock, &TagID );

      /* File Set Descriptor */
      if( TagID == 256 )  /* File Set Descriptor */
        UDFLongAD( &LogBlock[ 400 ], &RootICB );
    } while( ( lbnum < partition.Start + partition.Length )
             && ( TagID != 8 ) && ( TagID != 256 ) );

    /* Sanity checks. */
    if( TagID != 256 )
      return 0;
    if( RootICB.Partition != 0 )
      return 0;
    SetUDFCache(device, RootICBCache, 0, &RootICB);
  }

  /* Find root dir */
  if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) )
    return 0;
  if( filetype != 4 )
    return 0;  /* Root dir should be dir */
  {
    int cache_file_info = 0;
    /* Tokenize filepath */
    token = strtok(tokenline, "/");

    while( token != NULL ) {
      if( !UDFScanDir( device, File, token, &partition, &ICB,
                       cache_file_info))
        return 0;
      if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) )
        return 0;
      if(!strcmp(token, "VIDEO_TS"))
        cache_file_info = 1;
      token = strtok( NULL, "/" );
    }
  }

  /* Sanity check. */
  if( File.Partition != 0 )
    return 0;
  *filesize = File.Length;
  /* Hack to not return partition.Start for empty files. */
  if( !File.Location )
    return 0;
  else
    return partition.Start + File.Location;
}
Example #7
0
static int UDFGetAVDP( dvd_reader_t *device,
                       struct avdp_t *avdp)
{
  uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ];
  uint8_t *Anchor = (uint8_t *)(((uintptr_t)Anchor_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum, MVDS_location, MVDS_length;
  uint16_t TagID;
  uint32_t lastsector;
  int terminate;
  struct avdp_t;

  if(GetUDFCache(device, AVDPCache, 0, avdp))
    return 1;

  /* Find Anchor */
  lastsector = 0;
  lbnum = 256;   /* Try #1, prime anchor */
  terminate = 0;

  for(;;) {
    if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
      UDFDescriptor( Anchor, &TagID );
    } else {
      TagID = 0;
    }
    if (TagID != 2) {
      /* Not an anchor */
      if( terminate ) return 0; /* Final try failed */

      if( lastsector ) {
        /* We already found the last sector.  Try #3, alternative
         * backup anchor.  If that fails, don't try again.
         */
        lbnum = lastsector;
        terminate = 1;
      } else {
        /* TODO: Find last sector of the disc (this is optional). */
        if( lastsector )
          /* Try #2, backup anchor */
          lbnum = lastsector - 256;
        else
          /* Unable to find last sector */
          return 0;
      }
    } else
      /* It's an anchor! We can leave */
      break;
  }
  /* Main volume descriptor */
  UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
  avdp->mvds.location = MVDS_location;
  avdp->mvds.length = MVDS_length;

  /* Backup volume descriptor */
  UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
  avdp->rvds.location = MVDS_location;
  avdp->rvds.length = MVDS_length;

  SetUDFCache(device, AVDPCache, 0, avdp);

  return 1;
}
Example #8
0
/**
 * Dir: Location of directory to scan
 * FileName: Name of file to look for
 * FileICB: Location of ICB of the found file
 * return 1 on success, 0 on error;
 */
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
                       struct Partition *partition, struct AD *FileICB,
                       int cache_file_info)
{
  char filename[ MAX_UDF_FILE_NAME_LEN ];
  uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048];
  uint8_t *directory = (uint8_t *)(((uintptr_t)directory_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum;
  uint16_t TagID;
  uint8_t filechar;
  unsigned int p;
  uint8_t *cached_dir_base = NULL, *cached_dir;
  uint32_t dir_lba;
  struct AD tmpICB;
  int found = 0;
  int in_cache = 0;

  /* Scan dir for ICB of file */
  lbnum = partition->Start + Dir.Location;

  if(DVDUDFCacheLevel(device, -1) > 0) {
    /* caching */

    if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
      dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
      if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL)
        return 0;
      cached_dir = (uint8_t *)(((uintptr_t)cached_dir_base & ~((uintptr_t)2047)) + 2048);
      if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
        free(cached_dir_base);
        cached_dir_base = NULL;
        cached_dir = NULL;
      }
      /*
      if(cached_dir) {
        fprintf(stderr, "malloc dir: %d\n",  dir_lba * DVD_VIDEO_LB_LEN);
      }
      */
      {
        uint8_t *data[2];
        data[0] = cached_dir_base;
        data[1] = cached_dir;
        SetUDFCache(device, LBUDFCache, lbnum, data);
      }
    } else
      in_cache = 1;

    if(cached_dir == NULL) {
      free(cached_dir_base);
      return 0;
    }

    p = 0;

    while( p < Dir.Length ) {
      UDFDescriptor( &cached_dir[ p ], &TagID );
      if( TagID == 257 ) {
        p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
                                filename, &tmpICB );
        if(cache_file_info && !in_cache) {
          uint8_t tmpFiletype;
          struct AD tmpFile;

          if( !strcasecmp( FileName, filename ) ) {
            memcpy(FileICB, &tmpICB, sizeof(tmpICB));
            found = 1;
          }
          UDFMapICB(device, tmpICB, &tmpFiletype, partition, &tmpFile);
        } else {
          if( !strcasecmp( FileName, filename ) ) {
            memcpy(FileICB, &tmpICB, sizeof(tmpICB));
            return 1;
          }
        }
      } else {
        if(cache_file_info && (!in_cache) && found)
          return 1;
        return 0;
      }
    }
    if(cache_file_info && (!in_cache) && found)
      return 1;
    return 0;
  }

  if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 )
    return 0;

  p = 0;
  while( p < Dir.Length ) {
    if( p > DVD_VIDEO_LB_LEN ) {
      ++lbnum;
      p -= DVD_VIDEO_LB_LEN;
      Dir.Length -= DVD_VIDEO_LB_LEN;
      if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
        return 0;
      }
    }
    UDFDescriptor( &directory[ p ], &TagID );
    if( TagID == 257 ) {
      p += UDFFileIdentifier( &directory[ p ], &filechar,
                              filename, FileICB );
      if( !strcasecmp( FileName, filename ) ) {
        return 1;
      }
    } else
      return 0;
  }

  return 0;
}
Example #9
0
static int UDFCacheDir( UDF_DIR *device, struct AD Dir,
                       struct Partition *partition, struct AD *FileICB)
{
	char filename[ MAX_UDF_FILE_NAME_LEN ];
	uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048];
	uint8_t *directory = (uint8_t *)(((uintptr_t)directory_base & ~((uintptr_t)2047)) + 2048);
	uint32_t lbnum;
	uint16_t TagID;
	uint8_t filechar;
	unsigned int p;
	uint8_t *cached_dir_base = NULL, *cached_dir;
	uint32_t dir_lba;
	struct AD tmpICB;
	int in_cache = 0;
	uint32_t file_num = 0;

	/* Scan dir for ICB of file */
	//lbnum = partition->Start + Dir.Location;
	lbnum = UDFGetBlock(partition, Dir.Partition, Dir.Location);

	if(BDUDFCacheLevel(device->udf_data, -1) > 0) {
		/* caching */

		if(!GetBDUDFCache(device->udf_data, LBUDFCache, lbnum, &cached_dir)) {
			dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
			if((cached_dir_base = (uint8_t*)malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL)
				return 0;
			cached_dir = (uint8_t *)(((uintptr_t)cached_dir_base & ~((uintptr_t)2047)) + 2048);
			if( DVDReadLBUDF( device->udf_data, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
				free(cached_dir_base);
				cached_dir_base = NULL;
				cached_dir = NULL;
			}
			/*
			   if(cached_dir) {
			   fprintf(stderr, "malloc dir: %d\n",  dir_lba * DVD_VIDEO_LB_LEN);
			   }
			   */
			{
				uint8_t *data[2];
				data[0] = cached_dir_base;
				data[1] = cached_dir;
				SetUDFCache(device->udf_data, LBUDFCache, lbnum, data);
			}
		} else
			in_cache = 1;

		if(cached_dir == NULL)
			return 0;

		p = 0;

		device->aloc_num = 5;
		device->file_name = malloc(256 * device->aloc_num);
		while( p < Dir.Length ) {
			UDFDescriptor( &cached_dir[ p ], &TagID );
			//printf("aaa TagID: %d, len: %d\n", TagID, Dir.Length);
			if( TagID == 257 ) {
				p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
						filename, &tmpICB );
				if (filename[0] == '\0')
					continue;
				if (file_num + 1 > device->aloc_num)
				{
					device->aloc_num += 5;
					device->file_name = realloc((void *)device->file_name, 256 * device->aloc_num);
				}
				//printf("add filename: '%s'\n", filename);
				strncpy((char *)(device->file_name + file_num), filename, 256);
				device->file_num = ++file_num;
			} else {
				return 0;
			}
		}
		return 1;
	}

	if( DVDReadLBUDF( device->udf_data, lbnum, 2, directory, 0 ) <= 0 )
		return 0;

	p = 0;
	while( p < Dir.Length ) {
		if( p > DVD_VIDEO_LB_LEN ) {
			++lbnum;
			p -= DVD_VIDEO_LB_LEN;
			Dir.Length -= DVD_VIDEO_LB_LEN;
			if( DVDReadLBUDF( device->udf_data, lbnum, 2, directory, 0 ) <= 0 ) {
				return 0;
			}
		}
		UDFDescriptor( &directory[ p ], &TagID );
		if( TagID == 257 ) {
			p += UDFFileIdentifier( &directory[ p ], &filechar,
					filename, FileICB );
			//printf("filename2: %s\n", filename);
		}
	}

	return 0;
}
Example #10
0
uint32_t BDUDFDirFile( UDF_DIR *device, const char *filename)
{
  uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum;
  uint16_t TagID;
  struct Partition partition;
  struct AD RootICB, File, ICB;
  char tokenline[ MAX_UDF_FILE_NAME_LEN ];
  char *token;
  uint8_t filetype;

  tokenline[0] = '\0';
  strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1);
  memset(&ICB, 0, sizeof(struct AD));
  memset(&File, 0, sizeof(struct AD));
  memset(&RootICB, 0, sizeof(struct AD));
  memset(&partition, 0, sizeof(struct Partition));

  if(!(GetBDUDFCache(device->udf_data, PartitionCache, 0, &partition) &&
       GetBDUDFCache(device->udf_data, RootICBCache, 0, &RootICB))) {
    /* Find partition, 0 is the standard location for DVD Video.*/
    if( !UDFFindPartition( device->udf_data, 0, &partition ) )
	{
		UDFFreePartition(&partition);
		return 0;
	}

    /* Find root dir ICB */
    //lbnum = partition.Start;
  lbnum = UDFGetBlock(&partition, partition.vol.FSD.Partition, partition.vol.FSD.Location);
    do {
      if( DVDReadLBUDF( device->udf_data, lbnum++, 1, LogBlock, 0 ) <= 0 )
        TagID = 0;
      else
        UDFDescriptor( LogBlock, &TagID );

      /* File Set Descriptor */
      if( TagID == 256 )  /* File Set Descriptor */
	  {
        UDFLongAD( &LogBlock[ 400 ], &RootICB );
		partition.Number = RootICB.Partition;
	  }
    } while( ( lbnum < partition.Start + partition.Length )
             && ( TagID != 8 ) && ( TagID != 256 ) );

    SetUDFCache(device->udf_data, PartitionCache, 0, &partition);

    /* Sanity checks. */
    if( TagID != 256 )
      return 0;
    //if( RootICB.Partition != 0 )
    //  return 0;
    SetUDFCache(device->udf_data, RootICBCache, 0, &RootICB);
  }

  /* Find root dir */
  if( !UDFMapICB( device->udf_data, RootICB, &filetype, &partition, &File ) )
    return 0;
  if( filetype != 4 )
    return 0;  /* Root dir should be dir */
  {
    /* Tokenize filepath */
    token = strtok(tokenline, "/");

    while( token != NULL ) {
      if( !UDFScanDir( device->udf_data, File, token, &partition, &ICB, 0) )
        return 0;
	  //printf("icb: part: %u, block: %u\n", ICB.Partition, ICB.Location);
      if( !UDFMapICB( device->udf_data, ICB, &filetype, &partition, &File ) )
        return 0;
	  //printf("file: part: %u, block: %u\n", File.Partition, File.Location);
      token = strtok( NULL, "/" );
    }
	if( UDFCacheDir( device, File, &partition, &ICB) )
	{
		return 1;
	}
  }

  return 0;
}
Example #11
0
/**
 * Looks for partition on the disc.  Returns 1 if partition found, 0 on error.
 *   partnum: Number of the partition, starting at 0.
 *   part: structure to fill with the partition information
 */
static int UDFFindPartition( UDF_DATA *device, int partnum,
                             struct Partition *part )
{
  uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
  uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
  uint32_t lbnum, MVDS_location, MVDS_length;
  uint16_t TagID;
  int i, volvalid;
  struct avdp_t avdp;
  uint8_t file_type;

  if(!UDFGetAVDP(device, &avdp))
    return 0;

  /* Main volume descriptor */
  MVDS_location = avdp.mvds.location;
  MVDS_length = avdp.mvds.length;

  part->valid = 0;
  volvalid = 0;
  //part->VolumeDesc[ 0 ] = '\0';
  i = 1;
  do {
    /* Find Volume Descriptor */
    lbnum = MVDS_location;
    do {

      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
		  return 0;
        TagID = 0;
	  } else
        UDFDescriptor( LogBlock, &TagID );

      if( ( TagID == 5 ) && ( !part->valid ) ) {
        /* Partition Descriptor */
        UDFPartition( LogBlock, &part->Flags, &part->Number,
                      part->Contents, &part->Start, &part->Length );
        part->valid = ( partnum == part->Number );
      } else if( ( TagID == 6 ) && ( !volvalid ) ) {
        /* Logical Volume Descriptor */
        if( UDFLogVolume( LogBlock, &part->vol) ) {
          /* TODO: sector size wrong! */
        } else
          volvalid = 1;
      }

    } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
               / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
             && ( ( !part->valid ) || ( !volvalid ) ) );

    if( ( !part->valid) || ( !volvalid ) ) {
      /* Backup volume descriptor */
      MVDS_location = avdp.mvds.location;
      MVDS_length = avdp.mvds.length;
    }
  } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );

  /* load metadata for udf 2.50 */
  if (volvalid == 1)
  {
	  struct PartitionMaps *Maps;
	  for (i = 0; i < (int)part->vol.MapNum; i++)
	  {
		  Maps = &part->vol.Maps[i];
		  if (Maps->MapType == UDF_METADATA_MAP25)
		  {
			  /* metadta file location */
			  //printf("metadata at partition: %d loc: %d\n", Maps->PartitionNum, Maps->mdata.meta_file_loc);
			  lbnum = UDFGetBlock(part, Maps->PartitionNum, Maps->mdata.meta_file_loc);
			  if( DVDReadLBUDF( device, lbnum, 1, LogBlock, 0 ) <= 0 )
			  {
			  } else {
				  UDFDescriptor( LogBlock, &TagID );
				  if (TagID == 266)
				  {
					  UDFExtFileEntry(LogBlock, &file_type, part, &Maps->meta_ad);
				  }
				  //UDFExtFileEntry(LogBlock, part, &Maps->meta_ad);
				  //printf("ad: %u, %u, %x, %u\n", Maps->meta_ad.Location, Maps->meta_ad.Length, Maps->meta_ad.Flags, Maps->meta_ad.Partition);
			  }
			  //printf("mirror at partition: %d loc: %d\n", Maps->PartitionNum, Maps->mdata.mirror_file_loc);
			  /*
			  if( DVDReadLBUDF( device, part->Start + Maps->mdata.mirror_file_loc, 1, LogBlock, 0 ) <= 0 )
			  {
			  } else {
				  printf("%02x %02x %02x %02x\n", LogBlock[0], LogBlock[1], LogBlock[2], LogBlock[3]);
			  }
			  */
		  }
	  }

	  // use file set descriptor to find root icb
	  /*
	  lbnum = UDFGetBlock(part, part->vol.FSD.Partition, part->vol.FSD.Location);
	  if( DVDReadLBUDF( device, lbnum, 1, LogBlock, 0 ) <= 0 )
	  {
	  } else {
		  printf("%02x %02x\n", LogBlock[0], LogBlock[1]);
	  }
	  */
  }

  /* We only care for the partition, not the volume */
  return part->valid;
}
Example #12
0
uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
                      uint32_t *filesize )
{
  uint8_t *LogBlock;
  uint32_t lbnum;
  uint16_t TagID;
  struct Partition partition;
  struct AD RootICB, File, ICB;
  char tokenline[ MAX_UDF_FILE_NAME_LEN ];
  char *token;
  uint8_t filetype;
  
  if(filesize) {
    *filesize = 0;
  }
  tokenline[0] = '\0';
  strcat( tokenline, filename );

    
  if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
       GetUDFCache(device, RootICBCache, 0, &RootICB))) {
    /* Find partition, 0 is the standard location for DVD Video.*/
    if( !UDFFindPartition( device, 0, &partition ) ) {
      return 0;
    }
    SetUDFCache(device, PartitionCache, 0, &partition);
    
    LogBlock = dvdalign_lbmalloc(device, 1);
    if(!LogBlock) {
      return 0;
    }
    /* Find root dir ICB */
    lbnum = partition.Start;
    do {
      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
        TagID = 0;
      } else {
        UDFDescriptor( LogBlock, &TagID );
      }

      /* File Set Descriptor */
      if( TagID == 256 ) {  // File Set Descriptor
        UDFLongAD( &LogBlock[ 400 ], &RootICB );
      }
    } while( ( lbnum < partition.Start + partition.Length )
             && ( TagID != 8 ) && ( TagID != 256 ) );

    dvdalign_lbfree(device, LogBlock);
      
    /* Sanity checks. */
    if( TagID != 256 ) {
      return 0;
    }
    if( RootICB.Partition != 0 ) {
      return 0;
    }
    SetUDFCache(device, RootICBCache, 0, &RootICB);
  }

  /* Find root dir */
  if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) {
    return 0;
  }
  if( filetype != 4 ) {
    return 0;  /* Root dir should be dir */
  }
  {
    int cache_file_info = 0;
    /* Tokenize filepath */
    token = strtok(tokenline, "/");
    
    while( token != NULL ) {
      
      if( !UDFScanDir( device, File, token, &partition, &ICB,
                       cache_file_info)) {
        return 0;
      }
      if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) {
        return 0;
      }
      if(!strcmp(token, "VIDEO_TS")) {
        cache_file_info = 1;
      }
      token = strtok( NULL, "/" );
    }
  } 

  /* Sanity check. */
  if( File.Partition != 0 ) {
    return 0;
  }

  if(filesize) {
    *filesize = File.Length;
  }
  /* Hack to not return partition.Start for empty files. */
  if( !File.Location ) {
    return 0;
  } else {
    return partition.Start + File.Location;
  }
}
Example #13
0
static int UDFGetAVDP( dvd_reader_t *device,
                       struct avdp_t *avdp)
{
  uint8_t *Anchor;
  uint32_t lbnum, MVDS_location, MVDS_length;
  uint16_t TagID;
  uint32_t lastsector;
  int terminate;
  struct avdp_t; 
  
  if(GetUDFCache(device, AVDPCache, 0, avdp)) {
    return 1;
  }
  
  /* Find Anchor */
  lastsector = 0;
  lbnum = 256;   /* Try #1, prime anchor */
  terminate = 0;
  
  Anchor = dvdalign_lbmalloc(device, 1);
  if(!Anchor) {
    return 0;
  }
  for(;;) {
    if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
      UDFDescriptor( Anchor, &TagID );
    } else {
      TagID = 0;
    }
    if (TagID != 2) {
      /* Not an anchor */
      if( terminate ) {
        dvdalign_lbfree(device, Anchor);
        errno = EMEDIUMTYPE;
        return 0; /* Final try failed */
      } 
      
      if( lastsector ) {
        /* We already found the last sector.  Try #3, alternative
         * backup anchor.  If that fails, don't try again.
         */
        lbnum = lastsector;
        terminate = 1;
      } else {
        /* TODO: Find last sector of the disc (this is optional). */
        if( lastsector ) {
          /* Try #2, backup anchor */
          lbnum = lastsector - 256;
        } else {
          /* Unable to find last sector */
          dvdalign_lbfree(device, Anchor);
          errno = EMEDIUMTYPE;
          return 0;
        }
      }
    } else {
      /* It's an anchor! We can leave */
      break;
    }
  }
  /* Main volume descriptor */
  UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
  avdp->mvds.location = MVDS_location;
  avdp->mvds.length = MVDS_length;
  
  /* Backup volume descriptor */
  UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
  avdp->rvds.location = MVDS_location;
  avdp->rvds.length = MVDS_length;
  
  SetUDFCache(device, AVDPCache, 0, avdp);
  
  dvdalign_lbfree(device, Anchor);
  return 1;
}
Example #14
0
/**
 * Dir: Location of directory to scan
 * FileName: Name of file to look for
 * FileICB: Location of ICB of the found file
 * return 1 on success, 0 on error;
 */
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
                       struct Partition *partition, struct AD *FileICB,
                       int cache_file_info) 
{
  char filename[ MAX_UDF_FILE_NAME_LEN ];
  uint8_t *directory;
  uint32_t lbnum;
  uint16_t TagID;
  uint8_t filechar;
  unsigned int p;
  uint8_t *cached_dir = NULL;
  uint32_t dir_lba;
  struct AD tmpICB;
  int found = 0;
  int in_cache = 0;

  /* Scan dir for ICB of file */
  lbnum = partition->Start + Dir.Location;
    
  if(DVDUDFCacheLevel(device, -1) > 0) {
    /* caching */
      
    if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
      dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
      if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) {
        return 0;
      }
      if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
        dvdalign_lbfree(device, cached_dir);
        cached_dir = NULL;
      }
      SetUDFCache(device, LBUDFCache, lbnum, &cached_dir);
    } else {
      in_cache = 1;
    }
      
    if(cached_dir == NULL) {
      return 0;
    }
      
    p = 0;
      
    while( p < Dir.Length ) {
      UDFDescriptor( &cached_dir[ p ], &TagID );
      if( TagID == 257 ) {
        p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
                                filename, &tmpICB );
        if(cache_file_info && !in_cache) {
          uint8_t tmpFiletype;
          struct AD tmpFile;
            
          if( !strcasecmp( FileName, filename ) ) {
            *FileICB = tmpICB;
            found = 1;
              
          }
          UDFMapICB(device, tmpICB, &tmpFiletype,
                    partition, &tmpFile);
        } else {
          if( !strcasecmp( FileName, filename ) ) {
            *FileICB = tmpICB;
            return 1;
          }
        }
      } else {
        if(cache_file_info && (!in_cache) && found) {
          return 1;
        }
        return 0;
      }
    }
    if(cache_file_info && (!in_cache) && found) {
      return 1;
    }
    return 0;
  }

  directory = dvdalign_lbmalloc(device, 2);
  if(!directory) {
    return 0;
  }
  if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
    dvdalign_lbfree(device, directory);
    return 0;
  }

  p = 0;
  while( p < Dir.Length ) {
    if( p > DVD_VIDEO_LB_LEN ) {
      ++lbnum;
      p -= DVD_VIDEO_LB_LEN;
      Dir.Length -= DVD_VIDEO_LB_LEN;
      if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
        dvdalign_lbfree(device, directory);
        return 0;
      }
    }
    UDFDescriptor( &directory[ p ], &TagID );
    if( TagID == 257 ) {
      p += UDFFileIdentifier( &directory[ p ], &filechar,
                              filename, FileICB );
      if( !strcasecmp( FileName, filename ) ) {
        dvdalign_lbfree(device, directory);
        return 1;
      }
    } else {
      dvdalign_lbfree(device, directory);
      return 0;
    }
  }

  dvdalign_lbfree(device, directory);
  return 0;
}