ISO 9660文件系统,有详细资料吗?
研究了两天,没找到详细的资料,大神有详细资料没?最近想研究下ISO内文件列表。
想通过API创建还是 2012jiashanni 发表于 2020-1-31 18:37
想通过API创建还是
解析已存在的ISO文件内部文件列表。
----------------------------
Windows有API可以创建ISO吗? 红毛樱木 发表于 2020-1-31 18:46
解析已存在的ISO文件内部文件列表。
----------------------------
Windows有API可以创建ISO吗?
就是判断ISO是 ISO 9660还是UDF?还是想获取 ISO 9660格式的ISO里的文件内容? 2012jiashanni 发表于 2020-1-31 18:46
就是判断ISO是 ISO 9660还是UDF?还是想获取 ISO 9660格式的ISO里的文件内容?
就是解析ISO文件系统。
简单说就是想获取ISO文件里的文件列表。
比如获取A.ISO文件里的文件列表 本帖最后由 sunsea 于 2020-1-31 19:14 编辑
当年参考https://blog.csdn.net/goodqt/article/details/17202109这个帖子写的一个小程序,提取ISO内文件的,现在可能还对你有参考价值吧。
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <tchar.h>
#include <string>
#include <vector>
#include <mbstring.h>
#include <stdlib.h>
using namespace std;
#ifdef _UNICODE
typedef wstring _tstring;
#else
typedef string _tstring;
#endif
#define ATAPI_SECTOR_SIZE 2048 //一个CD扇区2048Byte
#define LBA_TO_BYTE(x) (x*ATAPI_SECTOR_SIZE)
//用法isodr.exe <iso文件> <光盘内路径> <输出路径>
//例:isodr.exe C:\abc.iso /boot/boot.sdi C:\abc.tmp
//例:isodr.exe C:\abc.iso /bootmgr C:\bootmgr //输出根目录下的bootmgr
//直接运行程序显示本帮助。
struct FILE_ITEM{
unsigned long lba;
string FileName;
unsigned long size;
};
int _t_real_main(int argc, _TCHAR* argv[]);
int PraseFileSystemAndFind(FILE* isofile,unsigned long lba,FILE_ITEM &item,int depth,const vector<string> &NeedFileName,bool &isfound);
int _tmain(int argc, _TCHAR* argv[])
{
_TCHAR *help_txt = _T("ISO文件直接读取工具\t作者:sunsea\t参考网上部分代码改编而成\n高歌酹酒,来者相候,唤我今日,长缨在手。\n\n用法isodr.exe <iso文件> <光盘内路径> <输出路径>\n例:isodr.exe C:\\abc.iso /boot/boot.sdi C:\\abc.tmp\n例:isodr.exe C:\\abc.iso /bootmgr C:\\bootmgr 输出根目录下的bootmgr\n\n直接运行程序显示本帮助。");
setlocale(LC_ALL,"chs");
if (argc==1) {
_tprintf(help_txt);
}
if (argc>1){
return _t_real_main(argc,argv);
}
return 0;
}
inline size_t seek_and_read(FILE* file,void* buf,unsigned long offest,unsigned long length){
fseek(file,offest,SEEK_SET);
return fread(buf,length,1,file);
}
int _t_real_main(int argc, _TCHAR* argv[]){
//这里是真正做事情的代码。
//先检查源文件是否存在。
_TCHAR *source_filename=argv;
FILE * source_iso=NULL;
FILE_ITEM myFile;//目标文件
source_iso=_tfopen(source_filename,_T("rb"));
if (source_iso==NULL)
{
_ftprintf(stderr,_T("源ISO镜像打开失败!请检查文件。"));
return -1;
}
FILE *output=_tfopen(argv,_T("wb"));
if (output==NULL){
_ftprintf(stderr,_T("目标文件打开失败!请检查文件。"));
return -1;
}
char buf_sector_1;
/* iso的前32768字节被保留,检查CD001标志*/
unsigned long lba = (0x8000 / 0x800); /*从0x8000的地方开始寻找.*/
for(;;++lba)
{
//ISO9660最大允许整个iso 2G大小。
if(!seek_and_read(source_iso,buf_sector_1,LBA_TO_BYTE(lba),ATAPI_SECTOR_SIZE)) { //读一个扇区
_ftprintf(stderr,_T("源ISO镜像读取错误!请检查文件。"));
return -1;
}
/*Identifier is always "CD001".*/
if(buf_sector_1 != 'C' ||
buf_sector_1 != 'D' ||
buf_sector_1 != '0' ||
buf_sector_1 != '0' ||
buf_sector_1 != '1' ) /*判断CD001 不符合直接返回.*/
{
_ftprintf(stderr,_T("源ISO镜像非法!"));
return -1;
}
if(buf_sector_1 == 0xff) /*Volume Descriptor Set Terminator.*/
return -1; /*如果这是最后一个 也返回.*/
if(buf_sector_1 != 0x01 /*Primary Volume Descriptor.*/)
continue; /*不是Primary Volume Descriptor就继续*/
/*Directory entry for the root directory.*/
if(buf_sector_1 != 0x22 /*Msut 34.*/)
return -1;
/*Location of extent (LBA) in both-endian format.*/
lba = *(unsigned long *)(buf_sector_1 + 156 + 2);
break; /*读LBA,跳出.*/
}
//分析文件名。分解出目录
string Temp;
vector<string> WantedFileName;
char *token = NULL;
char *next_token = NULL;
char *Wanted;
bool isfound=false;
#ifdef _UNICODE
int need=0;
need=wcstombs(NULL,argv,0)+1;
Wanted = new char;
wcstombs(Wanted,argv,need);
#else
Wanted = new char)+1];
strcpy(Wanted,argv);
#endif
token=strtok_s(Wanted,"/",&next_token);
while (token != NULL)
{
if (token != NULL)
{
Temp=token;
WantedFileName.push_back(Temp);
token = strtok_s(NULL,"/", &next_token);
}
}
delete [] Wanted;//切分完毕
PraseFileSystemAndFind(source_iso,lba,myFile,0,WantedFileName,isfound);
if (!isfound){
_ftprintf(stderr,_T("没找到你要的文件!"));
}else{
_tprintf(_T("找到目标文件,大小%d,LBA %d\n"),myFile.size,myFile.lba);
fseek(source_iso,LBA_TO_BYTE(myFile.lba),SEEK_SET);
char buffer; //按4K一块
for (unsigned int i=0;i<=(myFile.size/4096);i++){
if (i==(myFile.size/4096)){
//最后一块
fread(buffer,myFile.size-i*4096,1,source_iso);
fwrite(buffer,myFile.size-i*4096,1,output);
_tprintf(_T("输出完毕。"));
}else{
fread(buffer,4096,1,source_iso);
fwrite(buffer,4096,1,output);
}
}
}
fclose(output);
fclose(source_iso);
if (!isfound){
_tremove(argv);
}
return 0;
}
int PraseFileSystemAndFind(FILE* isofile,unsigned long lba,FILE_ITEM &item,int depth,const vector<string> &NeedFileName,bool &isfound){
isfound=false;
char SectorBuf;
seek_and_read(isofile,SectorBuf,LBA_TO_BYTE(lba),ATAPI_SECTOR_SIZE);
unsigned long offset = 0; /*要读的文件(夹)的信息结构的偏移.*/
bool isDir = 0; /*是否是文件夹.*/
bool needRead = 0; /*需不需要重新读.*/
for(;;offset += SectorBuf /*Length of Directory Record.*/)
{
while(offset >= ATAPI_SECTOR_SIZE)
{
offset -= ATAPI_SECTOR_SIZE;
++lba;
needRead = 1;
/*Read again.*/
} /*偏移超出这个扇区的范围就修正一下.*/
if(needRead)
seek_and_read(isofile,SectorBuf,LBA_TO_BYTE(lba),ATAPI_SECTOR_SIZE);
needRead = 0;
if(SectorBuf == 0x0) /*No more.*/
break; /*大小是0说明结束了,退出.*/
/*Location of extent (LBA) in both-endian format.*/
unsigned long fileLBA = *(unsigned long *)(SectorBuf + offset + 0x2);
if(fileLBA <= lba)
continue; /*获取文件LBA,小于就继续吧.*/
isDir = SectorBuf & 0x2; /*Is it a dir?*/
unsigned long filesize = *(unsigned long *)(SectorBuf + offset + 10);
/*Length of file identifier (file name).
* This terminates with a ';' character
* followed by the file ID number in ASCII coded decimal ('1').*/
unsigned long filenameLength = SectorBuf;
//if(!isDir) /*如果是文件就要删掉最后的";1".*/
// filenameLength -= 2; /*Remove ';' and '1'.*/
char *filename =new char; /*Add 1 for '\0'.*/
memcpy(filename,
(const void *)(SectorBuf + offset + 33),
filenameLength); /*把文件名复制过来.*/
if((!isDir) && (filename == '_'))
filename = '.';
if((!isDir) && (filename == '.'))
filename = '\0';
else
filename = '\0'; /*做一些修正.*/
string _filename_safe = filename;
delete [] filename;
if(!isDir)
{
if(filesize != 0)
{
if (!stricmp(NeedFileName.c_str(),_filename_safe.c_str())) //找到了!
{
item.FileName=_filename_safe;
item.lba=fileLBA;
item.size=filesize;
isfound=true;
return 1;
}
}
}
else
{
if (!stricmp(NeedFileName.c_str(),_filename_safe.c_str()))
PraseFileSystemAndFind(isofile,fileLBA,item,depth+1,NeedFileName,isfound); /*对的就递归.*/
}
}
return 0;
}
编译结果就不放了,VS2005下编译通过,注意,输出的LBA是2048字节大扇区式的LBA。 sunsea 发表于 2020-1-31 19:13
当年参考https://blog.csdn.net/goodqt/article/details/17202109这个帖子写的一个小程序,提取ISO内文件的 ...
我也是看这里的,这里不全 红毛樱木 发表于 2020-1-31 19:14
我也是看这里的,这里不全
能按路径找到文件应该就能列出所有文件吧?或许可以试试能不能改造下这个程序列出所有文件和它们的LBA和长度,而且ISO9660还有个很棒的特点——所有文件都是连续的。
https://blog.csdn.net/perry_peng/article/details/7698673另外这里似乎还有个Python程序也能有帮助。
决定放弃了,ISO文件的文件系统太多了。
页:
[1]