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

📄 wrudf-cdr.c

📁 linux下的DVD格式udf文件读取库
💻 C
字号:
/*	wrudf-cdr.c  * */#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include "wrudf.h"#include "ide-pc.h"#include "bswap.h"char	*blockBuffer;uint32_t	newVATindex;uint32_t	sizeVAT;uint32_t	prevVATlbn;uint64_t  CDRuniqueID;			// from VAT FEuint32_t newVATentry() {    if( newVATindex + 10 > (sizeVAT >> 2) ) {		// ensure enough spave for regid and prevVATlbn	sizeVAT += 2048;	vat = realloc(vat, sizeVAT);	if( vat == NULL )	    printf("VAT reallocation failed\n");    }    /* could go through VAT and try to find unused 0xFFFFFFFF entry rather than alloc new one at the end */    vat[newVATindex] = getNWA() - pd->partitionStartingLocation;    return newVATindex++;}uint32_t	getNWA() {    if( devicetype == DISK_IMAGE )	return lseek(device, 0, SEEK_END) >> 11;    if( read_trackinfo(device, &ti, lastTrack) )	printf("Get Track Info failed\n");    if( ti.nwa_v )	return ti.nwa;    else	return INVALID;}uint32_t getMaxVarPktSize() {    struct cdrom_buffercapacity bc;    if( devicetype == DISK_IMAGE  )	return 1024 * 2048;			// nonsense value; just for testing    read_buffercapacity(device, &bc);    return ((bc.freeBufferLength >> 11) - 20) << 11;	// - 20 :: keep some spare blocks ???}char*	readCDR(uint32_t lbn, uint16_t partition) {    int		stat;    uint32_t	pbn = getPhysical(lbn, partition);    if( devicetype == DISK_IMAGE  ) {	stat = lseek(device, 2048 * pbn, SEEK_SET);	stat = read(device, blockBuffer, 2048);	if( stat != 2048 )	    fail("readCDR(hd) failed %m\n");	else	    return blockBuffer;    }    stat = readCD(device, sectortype, pbn, 1, blockBuffer);    if( stat ) {	if( ! ignoreReadError )	    printf("readCDR: %s\n", get_sense_string());	return NULL;    }    return blockBuffer;}    voidwriteHD(uint32_t physical, char* src) {    int		stat;    stat = lseek(device, 2048 * physical, SEEK_SET);    stat = write(device, src, 2048);    if( stat != 2048 ) {	printf("writeHD failed %m\n");    }}void syncCDR() {//    uint32_t nwa;    if( device == DISK_IMAGE )	return;    synchronize_cache(device);//    nwa = getNWA();//    printf("Link from %d to %d\n", nwa-7, nwa-1);}void writeHDlink() {    uint32_t blk = getNWA();    int		i;    for(i = 0; i < 7; i++ )	writeHD(blk+i, blockBuffer);}/*	writeBlockCDR() *	Writes one 2048 byte block */uint32_twriteCDR(void* src) {    uint32_t	physical;    physical = getNWA();//    printf("Write CDR sector %d\n", physical);    if( devicetype == DISK_IMAGE )	writeHD(physical, src);    else {	writeCD(device, physical, 1, src);    }    return physical;}/*	flagError *	split up extent in (1) good, (2) bad and (3) good subextents. *	In bad extent (2) set logicalBlockNum to zero *	If (1) is empty, maybe (2) can be merged with immediately preceding bad extent */long_ad *flagError(long_ad *extents, long_ad *ext, uint32_t pbn) {    uint32_t lbn = pbn - pd->partitionStartingLocation;    int	posInExtent = lbn - ext->extLocation.logicalBlockNum + 1;    int	blksInExtent = (ext->extLength + 2047) >> 11;    /* if there is a preceding extent which is bad and      * the current bad block is the first in this extent,      * then add this bad to the preceding extent     */    if( ext > extents && lbn == ext->extLocation.logicalBlockNum && !ext[-1].extLocation.logicalBlockNum ) {	if( ext[0].extLength < 2048 ) {	    ext[-1].extLength += ext[0].extLength;	    ext[0].extLength = 0;	} else {	    ext[-1].extLength += 2048;	    ext[0].extLength -= 2048;	    ext[0].extLocation.logicalBlockNum++;	}	return ext - 1;    }    /* watch one block extents */    if( blksInExtent == 1 ) {	ext[0].extLocation.logicalBlockNum = 0;	return ext;    }    /* 1st block of extent is bad */    if( posInExtent == 1 ) {	memmove(ext+1, ext, extents - ext + 62);	ext[0].extLength = 2048;	ext[0].extLocation.logicalBlockNum = 0;	ext[1].extLength -= 2048;	ext[1].extLocation.logicalBlockNum = lbn + 1;	return ext;    }    /* last block of extent is bad - watch partial block */    if( posInExtent == blksInExtent ) {	memmove(ext+1, ext, extents - ext + 62);	ext[1].extLength = ext->extLength - 2048;	ext[1].extLocation.logicalBlockNum = 0;	ext[0].extLength -= ext[1].extLength;	return ext;    }    /* middle block in extent is bad */    memmove(ext+2, ext, extents - ext + 61);    memcpy(ext+1, ext, sizeof(long_ad));    ext[0].extLength = 2048 * posInExtent;    ext[1].extLength = 2048;    ext[1].extLocation.logicalBlockNum = 0;    ext[2].extLength -= ext[0].extLength + 2048;    ext[2].extLocation.logicalBlockNum = lbn + 1;    return ext+1;}int verifyCDR(struct fileEntry *fe) {    long_ad	*ext, *extents;    int		processed;    int		stat, rv = 0;    uint32_t	pbn, pbnFE, rewriteBlkno;    setStrictRead(1);    extents = ext = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr);    processed = 0;    pbnFE = vat[fe->descTag.tagLocation] + pd->partitionStartingLocation;    pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation;    if( (fe->icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB )	goto FileEntryOnly;    do {	if( pbn > pbnFE ) {	    if( devicetype == DISK_IMAGE ) {		printf("Verify %d\n", pbn);		stat = 0;//		if( (pbn == 557) || pbn == 565 ) stat = 1;	/* for testing only */	    } else 		stat = readCD(device, sectortype, pbn, 1, blockBuffer);	    if( stat ) {		printf("readError %d : %s\n", pbn, get_sense_string());		rv++;		ext = flagError(extents, ext, pbn);		processed = ext->extLength - 2048;	    }	}	processed += 2048;	pbn++;	if( processed == ext->extLength ) {	    ext++;	    pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation;	    processed = 0;	}    } while (processed < ext->extLength);  FileEntryOnly:    if( rv == 0 ) {				/* no errors in data, now verify FileEntry */	int retries;	for( retries = 0; retries < 3; retries++ ) {	    if( devicetype == DISK_IMAGE ) {		printf("Verify %d\n", pbnFE);		stat = 0;//		if( pbnFE  == 552 || pbnFE == 553 ) stat = 1;	/* testing only */	    } else 		stat = readCD(device, sectortype, pbnFE, 1, blockBuffer);	    if( stat == 0 ) {		setStrictRead(0);		return 0;	    }	    printf("readError %d : %s\n", pbnFE, get_sense_string());	    pbnFE = getNWA();	    vat[fe->descTag.tagLocation] = pbnFE - pd->partitionStartingLocation;	    writeCDR(fe);	}	printf("verifyCDR: verify FE failed 3 times\n");     }    setStrictRead(0);    rewriteBlkno = getNWA() + 1 - pd->partitionStartingLocation;		// NWA itself for revised FileEntry    fe->lengthAllocDescs = 0;    for( ext = extents; ext->extLength; ext++ ) {	fe->lengthAllocDescs += sizeof(long_ad);	if( ext->extLocation.logicalBlockNum != 0 )	    continue;	ext->extLocation.logicalBlockNum = rewriteBlkno;	rewriteBlkno += ext->extLength >> 11;	if( ext->extLength & 2047 )	    break;    }    fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthExtendedAttr + fe->lengthAllocDescs - 16;    return rv;}void readVATtable() {    uint32_t 	blkno;    struct fileEntry *fe;    blkno = getNWA() - (devicetype == DISK_IMAGE ? 1 : 8);    prevVATlbn = blkno;    fe = (struct fileEntry*)readTaggedBlock(blkno, ABSOLUTE);    if( fe->descTag.tagIdent != TAG_IDENT_FE ||  fe->icbTag.fileType != 0 )	fail("VAT ICB not found\n");	    CDRuniqueID  = fe->uniqueID;    sizeVAT = ((fe->informationLength + 4095) & ~2047);    vat = malloc(sizeVAT);    memset(vat, 0xFF, sizeVAT);				// later or not at all    newVATindex = (fe->informationLength - 36) >> 2;    if( sizeof(*fe) + fe->lengthExtendedAttr + fe->informationLength <= 2048 ) {	memcpy(vat, fe->allocDescs + fe->lengthExtendedAttr, fe->informationLength - 36);    } else {	readExtents((char*)vat, 1, fe->allocDescs + fe->lengthExtendedAttr);    }}void writeVATtable() {    regid	*id;    struct fileEntry *fe;    int		stat, i, retries, size;    uint32_t	startBlk;    short_ad	*ext;    retries = 0;    id = (regid*)(&vat[newVATindex]);    memset(id, 0, sizeof(regid));    strcpy(id->ident, UDF_ID_ALLOC);    *(uint16_t*)id->identSuffix = 0x150;    id->identSuffix[2] = UDF_OS_CLASS_UNIX;    id->identSuffix[3] = UDF_OS_ID_LINUX;    *(uint32_t*)(id+1) = prevVATlbn;    fe = makeFileEntry();    size = (newVATindex + 9) << 2;    fe->informationLength = cpu_to_le64(size);    fe->descTag.tagSerialNum = lvid->descTag.tagSerialNum;    fe->icbTag.fileType = ICBTAG_FILE_TYPE_UNDEF;    fe->fileLinkCount = 0;    for( retries = 0; retries < 8; retries++ ) {	startBlk = getNWA();	if( sizeof(*fe) + size < 2048 ) {	    fe->icbTag.flags = ICBTAG_FLAG_AD_IN_ICB;	    memcpy(fe->allocDescs, vat, size);	    fe->lengthAllocDescs = cpu_to_le32(size);	} else {	    fe->logicalBlocksRecorded = (size + 2047) >> 11;	    fe->icbTag.flags = ICBTAG_FLAG_AD_SHORT;	    ext = (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr);	    ext->extLength = size;	    ext->extPosition = startBlk  - pd->partitionStartingLocation;	    fe->lengthAllocDescs = cpu_to_le32(16);	}	fe->descTag.tagLocation = startBlk  - pd->partitionStartingLocation + fe->logicalBlocksRecorded;	fe->descTag.descCRCLength = sizeof(*fe) + fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag);	setChecksum(&fe->descTag);	for( i = 0; i < fe->logicalBlocksRecorded; i++ )	    writeCDR(vat + (i<<9));	writeCDR(fe);	setStrictRead(1);	for( i = 0; i <= fe->logicalBlocksRecorded; i++ ) {	// "<=" so including FileEntry 	    if( devicetype == DISK_IMAGE ) {		printf("Verify %d\n", startBlk+i);		stat = 0;	    } else		stat = readCD(device, sectortype, startBlk + i, 1, blockBuffer);	    if( stat != 0 ) {		printf("writeVATtable verifyError %d : %s\n", startBlk + i, get_sense_string());		break;	    }	}	if( stat == 0 )	    break;    }    if( retries == 8 )	printf("*** writeVATtable rewrite FAILED\nLast VAT was at LBN %d\n", prevVATlbn);     setStrictRead(0);}

⌨️ 快捷键说明

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