我正在linux中编写一个程序,它计算Windows 7中CD卷的序列号(xxxx-xxxx)。我的程序正确地确定了文件系统iso9660和joilet的磁盘卷的序列号。但是如何使用文件系统udf定义磁盘卷嗅探器?有人能告诉我......
ps如果有人不明白我在谈论这种序列号https://extra-torrent.jimdo.com/2016/01/23/hard-disk-volume-serial-number-change/
#include <QCoreApplication>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <string.h>
#include <szi/szimac.h>
#include <qfile.h>
#include <iostream>
#include <QDir>
#include <unistd.h>
#define SEC_SIZE 2048
#define VD_N 16
#define VD_TYPE_SUPP 2
#define VD_TYPE_END 255
#define ESC_IDX 88
#define ESC_LEN 3
#define ESC_UCS2L1 "%/@"
#define ESC_UCS2L2 "%/C"
#define ESC_UCS2L3 "%/E"
using namespace std;
int cdid(unsigned char pvd[SEC_SIZE])
{
unsigned char part[4] = {0};
int i;
for(i = 0; i < SEC_SIZE; i += 4)
{
part[3] += pvd[i + 0];
part[2] += pvd[i + 1];
part[1] += pvd[i + 2];
part[0] += pvd[i + 3];
}
return (part[3] << 24) + (part[2] << 16) + (part[1] << 8) + part[0];
}
int main(int argc, char *argv[])
{
FILE *in;
unsigned char buf[SEC_SIZE];
struct cdrom_multisession msinfo;
long session_start;
int id;
QString home=QString(getenv("HOME"))+QString("/chteniestorm");
QFile file(home);
ustr="/dev/sr0";
in = fopen(ustr.toLocal8Bit().data(), "rb");
if(in == NULL)
{
if (file.open(QIODevice::WriteOnly))
{
file.write("sernom=1");
file.close();
}
cout<<"netdiska"<<endl;
return 0;
}
/* Get session info */
msinfo.addr_format = CDROM_LBA;
if(ioctl(fileno(in), CDROMMULTISESSION, &msinfo) != 0)
{
fprintf(stderr, "WARNING: Can't get multisession info\n");
perror(NULL);
session_start = 0;
}
else
{
session_start = msinfo.addr.lba;
}
fseek(in, 0, SEEK_SET); //to the begining
/* Seek to primary volume descriptor */
if(fseek(in, (session_start + VD_N) * SEC_SIZE, SEEK_SET) != 0)
{
if (file.open(QIODevice::WriteOnly))
{
file.write("sernom=2");
file.close();
}
fclose(in);
return 0;
}
/* Read descriptor */
if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
{
if (file.open(QIODevice::WriteOnly))
{
file.write("sernom=3");
file.close();
}
fclose(in);
return 0;
}
/* Caclculate disc id */
id = cdid(buf);
/* Search for Joliet extension */
while(buf[0] != VD_TYPE_END)
{
/* Read descriptor */
if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
{
perror(NULL);
return 0;
}
if(buf[0] == VD_TYPE_SUPP
&& (memcmp(buf + ESC_IDX, ESC_UCS2L1, ESC_LEN) == 0
|| memcmp(buf + ESC_IDX, ESC_UCS2L2, ESC_LEN) == 0
|| memcmp(buf + ESC_IDX, ESC_UCS2L3, ESC_LEN) == 0)
)
{
/* Joliet found */
id = cdid(buf);
}
}
fclose(in);
}
答案 0 :(得分:-1)
在更多地点[1],[2],[3],[4]上看到此问题的问题,但尚未得到答复。所以我会在这里做。
在其中一些帖子中,人们解码了序列号生成算法。它只是你已经找到的校验和并放入你的 cdid()函数中。 Windows上的ISO9660和UDF文件系统使用相同的校验和算法。您已经确定了哪个ISO9660结构是校验和计算的。
所以你的问题仍然只适用于UDF文件系统。对于Windows上的UDF文件系统,校验和是根据512字节长的文件集描述符(FSD)结构计算的。我建议你阅读OSTA UDF specification如何在UDF光盘上找到FSD。
基本上对于不使用虚拟分配表(VAT),备用表或元数据分区的普通UDF,FSD的位置存储在Logical Volume Descriptor(LVD)结构中,字段LogicalVolumeContentsUse(它的类型为long_ad)。 LVD存储在卷描述符序列(VDS)中。 VDS的位置存储在Anchor Volume Descriptor Pointer(AVDP)的MainVolumeDescriptorSequenceExtent字段中。 AVDP本身位于介质的256区。光学介质的扇区大小为2048字节,普通硬盘为512字节。
对于带增值税的UDF(例如在CD-R / DVD-R / BD-R上),备用表(例如在CD-RW / DVD-RW上)或元数据分区(例如在蓝光上),它很多更复杂。您需要查看虚拟,可分区或元数据分区,以了解如何将FSD的逻辑位置转换为媒体的物理位置。
在从版本2.0开始的udftools项目中,有一个新工具udfinfo,它提供有关UDF文件系统的各种信息。它还显示了 winserialnum 键下您的问题中的Windows特定卷序列号。请注意,udfinfo无法从包含VAT或元数据的UDF文件系统读取FSD。