⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvd_udf.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 2 页
字号:
  while( p < 176 + L_EA + L_AD ) {    switch( flags & 0x0007 ) {    case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8;  break;    case 1: UDFLongAD( &data[ p ], ad );  p += 16; break;    case 2: UDFExtAD( &data[ p ], ad );   p += 20; break;    case 3:      switch( L_AD ) {      case 8:  UDFShortAD( &data[ p ], ad, partition ); break;      case 16: UDFLongAD( &data[ p ], ad );  break;      case 20: UDFExtAD( &data[ p ], ad );   break;      }      p += L_AD;      break;    default:      p += L_AD; break;    }  }  return 0;}static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics,                              char *FileName, struct AD *FileICB ){  uint8_t L_FI;  uint16_t L_IU;  *FileCharacteristics = GETN1(18);  L_FI = GETN1(19);  UDFLongAD(&data[20], FileICB);  L_IU = GETN2(36);  if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName);  else FileName[0] = '\0';  return 4 * ((38 + L_FI + L_IU + 3) / 4);}/** * 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;}/** * 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;}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;}/** * 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;  uint32_t lbnum, MVDS_location, MVDS_length;  uint16_t TagID;  int i, volvalid;  struct avdp_t avdp;      if(!UDFGetAVDP(device, &avdp)) {    return 0;  }  LogBlock = dvdalign_lbmalloc(device, 1);  if(!LogBlock) {    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 ) ) );  dvdalign_lbfree(device, LogBlock);  /* We only care for the partition, not the volume */  return part->valid;}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;  }}/** * 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;}static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd){  uint8_t *pvd_buf;    if(GetUDFCache(device, PVDCache, 0, pvd)) {    return 1;  }    pvd_buf = dvdalign_lbmalloc(device, 1);  if(!pvd_buf) {    return 0;  }  if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) {    dvdalign_lbfree(device, pvd_buf);    return 0;  }    memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32);  memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128);  SetUDFCache(device, PVDCache, 0, pvd);    dvdalign_lbfree(device, pvd_buf);  return 1;}/** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * volid, place to put the string * volid_size, size of the buffer volid points to * returns the size of buffer needed for all data */int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid,                           unsigned int volid_size){  struct pvd_t pvd;  unsigned int volid_len;  /* get primary volume descriptor */  if(!UDFGetPVD(device, &pvd)) {    return 0;  }  volid_len = pvd.VolumeIdentifier[31];  if(volid_len > 31) {    /* this field is only 32 bytes something is wrong */    volid_len = 31;  }  if(volid_size > volid_len) {    volid_size = volid_len;  }  Unicodedecode(pvd.VolumeIdentifier, volid_size, volid);    return volid_len;}/** * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) * WARNING This is not a null terminated string * volsetid, place to put the data * volsetid_size, size of the buffer volsetid points to  * the buffer should be >=128 bytes to store the whole volumesetidentifier * returns the size of the available volsetid information (128) * or 0 on error */int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid,                              unsigned int volsetid_size){  struct pvd_t pvd;  /* get primary volume descriptor */  if(!UDFGetPVD(device, &pvd)) {    return 0;  }  if(volsetid_size > 128) {    volsetid_size = 128;  }    memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size);    return 128;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -