📄 wrudf-cdr.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 + -