📄 wrudf.c
字号:
/* wrudf.c * * Maintains a UDF filing system * */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/resource.h>#include "wrudf.h"#define WRUDF_VERSION "0.0.5"char *devicename; /* "/dev/cdrom" or disk image filename */int device; /* the file descriptor */int devicetype;enum MEDIUM medium;int ignoreReadError; /* used while reading VRS which may be absent on open CDR */#ifdef _GNU_SOURCEchar *line;#define GETLINE(prompt) readLine(prompt);#elsechar line[256];#define GETLINE(prompt) printf(prompt); fgets(line, 256, stdin); *strchr(line, '\n') = 0;#endifint cmndc;int cmndvSize;char** cmndv;#define FOUND_BEA01 1#define FOUND_NSR02 1<<1#define FOUND_TEA01 1<<2#define FOUND_PVD 1<<8#define FOUND_LVD 1<<9#define FOUND_PD 1<<10#define FOUND_USD 1<<11 uint32_t found;uint32_t options;Directory *rootDir, *curDir;timestamp timeStamp;regid entityWRUDF = { 0, "-wrudf (" WRUDF_VERSION ")", "\x04\x05"};extent_ad extentMainVolDescSeq;extent_ad extentRsrvVolDescSeq;extent_ad extentNextVolDescSeq;extent_ad extentLogVolIntegritySeq;uint32_t integrityDescBlocknumber; /* where to write LVID when finished */extent_ad extentLogVolIntegrityDesc; /* (continuation) extent for current LVIDs */extern uint64_t CDRuniqueID; /* in wrudf-cdr.c ex VAT FE */struct partitionDesc *pd; /* for the writeable partition */uint16_t virtualPartitionNum = 0xFFFF;uint32_t *vat;uint32_t newVATindex;uint32_t maxVATindex;uint32_t prevVATlbn;struct logicalVolDesc *lvd;struct unallocSpaceDesc *usd;struct spaceBitmapDesc *spaceMap;struct logicalVolIntegrityDesc *lvid;struct fileSetDesc *fsd;int usedSparingEntries;struct sparingTable *st;int spaceMapDirty, usdDirty, sparingTableDirty;char* readLine(char* prompt) { if( line ) { free(line); } return line = readline(prompt);}void initialise(char *devicename) { uint32_t i, len, blkno, lastblk, size; long_ad *fsdAd; short_ad *adSpaceMap; struct sparablePartitionMap *spm; char zeroes[5]; char fsdOut[91]; int fsdLen; struct generic_desc *p; struct volStructDesc *vsd; initIO(devicename); memset(zeroes, 0, 5); /* read Volume Recognition Sequence */ ignoreReadError = 1; for( blkno = 16; blkno < 256; blkno++ ) { vsd = readSingleBlock(blkno); if( vsd == NULL || memcmp(vsd->stdIdent, zeroes, 5) == 0 ) break; if( strncmp(vsd->stdIdent, "BEA01", VSD_STD_ID_LEN) == 0 ) { found |= FOUND_BEA01; continue; } if( strncmp(vsd->stdIdent, "NSR02", VSD_STD_ID_LEN) == 0 ) { found |= FOUND_NSR02; continue; } if( strncmp(vsd->stdIdent, "TEA01", 5) == 0 ) { found |= FOUND_TEA01; continue; } } ignoreReadError = 0; if( !(found & FOUND_BEA01) || !(found & FOUND_NSR02) || !(found & FOUND_TEA01) ) printf("No UDF VRS\n"); p = NULL; if( medium == CDR ) { p = readSingleBlock(512); if( p == NULL || p->descTag.tagIdent != TAG_IDENT_AVDP ) fail("No AVDP at block 512 on CDR disc\n"); } if( !p ) { p = readTaggedBlock(256, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) { p = readTaggedBlock(trackSize - 1, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) { p = readTaggedBlock(trackSize - 256, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) fail("No AVDP at block 256, N-256 or N-1 \n"); } } } extentMainVolDescSeq = ((struct anchorVolDescPtr*)p)->mainVolDescSeqExt; extentRsrvVolDescSeq = ((struct anchorVolDescPtr*)p)->reserveVolDescSeqExt; /* read Volume Descriptor Sequence */ blkno = extentMainVolDescSeq.extLocation; len = extentMainVolDescSeq.extLength; for( i = 0; i < len; blkno++, i += 2048 ) { int inMainSeq = 1; if( (p = readTaggedBlock(blkno, ABSOLUTE)) == NULL ) { if( !inMainSeq ) fail("Volume Descriptor Sequences read failure\n"); blkno = extentRsrvVolDescSeq.extLocation; len = extentRsrvVolDescSeq.extLength; inMainSeq = 0; i = 0; } switch( p->descTag.tagIdent ) { case TAG_IDENT_PVD: found |= FOUND_PVD; break; case TAG_IDENT_VDP: blkno = ((struct volDescPtr*)p)->nextVolDescSeqExt.extLocation - 1; len = ((struct volDescPtr*)p)->nextVolDescSeqExt.extLength; i = (uint32_t) -2048; break; case TAG_IDENT_IUVD: break; case TAG_IDENT_PD: /* must have one (re)writeable partition */ /* may have at most one RDONLY partition */ switch( ((struct partitionDesc *)p)->accessType ) { case PD_ACCESS_TYPE_READ_ONLY: break; case PD_ACCESS_TYPE_REWRITABLE: case PD_ACCESS_TYPE_WRITE_ONCE: found |= FOUND_PD; if( !pd ) pd = (struct partitionDesc*) calloc(512, 1); if( p->volDescSeqNum > pd->volDescSeqNum ) memcpy(pd, p, 512); break; default: printf("What to do with an accesstype %d partition?\n", ((struct partitionDesc*)p)->accessType); break; } break; case TAG_IDENT_LVD: found |= FOUND_LVD; if( !lvd ) lvd = (struct logicalVolDesc*) calloc(512, 1); if( p->volDescSeqNum > lvd->volDescSeqNum ) memcpy(lvd, p, 512); break; case TAG_IDENT_USD: found |= FOUND_USD; if( !usd ) usd = (struct unallocSpaceDesc*) calloc(512, 1); if( p->volDescSeqNum > usd->volDescSeqNum ) memcpy(usd, p, 512); break; case TAG_IDENT_TD: i = len; break; default: printf("Unexpected tag ID %04X\n in Volume Descriptor Sequence block %d", p->descTag.tagIdent, blkno); } } if( (found & FOUND_LVD) == 0 ) fail("No LVD found \n"); if( lvd->logicalBlockSize != 2048 ) fail("Blocksize not 2048\n"); spm = (struct sparablePartitionMap*)lvd->partitionMaps; for( i = 0; i < lvd->numPartitionMaps; i++ ) { if( spm->partitionMapType == 2 ) { if( strncmp( spm->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)) == 0 ) { int j; if( spm->sizeSparingTable > 2048 ) fail("Cannot handle SparingTable > 2048 bytes"); st = (struct sparingTable*)malloc(2048); p = readTaggedBlock(spm->locSparingTable[0], ABSOLUTE); memcpy(st, p, spm->sizeSparingTable); /* if #1 fails, try #2; should pick copy with highest sequenceNum */ for( j = usedSparingEntries = 0; j < (spm->sizeSparingTable >> 3); j++ ) { if( st->mapEntry[j].origLocation < 0xFFFFFFF0 ) usedSparingEntries++; } } else if( strncmp( spm->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)) == 0 ) virtualPartitionNum = i; } (char*)spm += spm->partitionMapLength; } if( medium == CDR ) { if( virtualPartitionNum != 0xFFFF ) readVATtable(); else fail("No Virtual Partition Map on CDR\n"); } if( medium != CDR && (found & FOUND_USD) == 0 ) fail("Did not find Unallocated Space Descriptor\n"); /* Read Fileset Descriptor Sequence */ fsdAd = (long_ad*) lvd->logicalVolContentsUse; for( i = 0; i < (fsdAd->extLength >> 11); i++ ) { blkno = pd->partitionStartingLocation + fsdAd->extLocation.logicalBlockNum + i; if( !(p = readTaggedBlock(blkno, ABSOLUTE)) ) exit(1); switch( p->descTag.tagIdent ) { case TAG_IDENT_TD: i = fsdAd->extLength; break; case TAG_IDENT_FSD: if( fsd && (lvd->volDescSeqNum > p->volDescSeqNum) ) break; fsd = (struct fileSetDesc*)malloc(512); memcpy(fsd, p, 512); break; default: printf("Unxpected tag id %d, where File Set Desc(256) expected\n", p->descTag.tagIdent); } } if( !fsd ) fail("No File Set Descriptor\n"); /* load Spacemap extent */ adSpaceMap = (short_ad*) &((struct partitionHeaderDesc*)pd->partitionContentsUse)->unallocSpaceBitmap; if( adSpaceMap->extLength != 0 ) { blkno = adSpaceMap->extPosition; len = adSpaceMap->extLength; spaceMap = (struct spaceBitmapDesc*) malloc((len + 2047) & ~2047); for( i = 0; i < len; i += 2048 ) { p = readBlock(blkno, 0); memcpy( (uint8_t*)spaceMap + i, (uint8_t*) p, 2048); freeBlock(blkno++, 0); } if( spaceMap->descTag.tagIdent != TAG_IDENT_SBD ) fail("SpaceBitmap not found\n"); } if (fsdLen = decode_utf8(fsd->fileSetIdent, fsdOut, fsd->fileSetIdent[31])) fsdOut[fsdLen] = '\0'; printf("You are going to update fileset '%s'\nProceed (y/N) : ", &fsdOut[1]); readLine(NULL); if( (line[0] | ' ') != 'y' ) fail("wrudf terminated\n"); /* Read Logical Volume Integrity sequence */ blkno = lvd->integritySeqExt.extLocation; lastblk = blkno + (lvd->integritySeqExt.extLength >> 11); extentLogVolIntegrityDesc = lvd->integritySeqExt; for( ; blkno < lastblk; blkno++ ) { if( !(p = readTaggedBlock(blkno, ABSOLUTE)) ) fail("Read failure in Integrity Sequence, blk %d\n", blkno); switch( p->descTag.tagIdent ) { case TAG_IDENT_TD: blkno = lastblk; break; case TAG_IDENT_LVID: size = sizeof(struct logicalVolIntegrityDesc) + sizeof(struct logicalVolIntegrityDescImpUse) + 2 * sizeof(uint32_t) * ((struct logicalVolIntegrityDesc*)p)->numOfPartitions; if( !lvid ) lvid = (struct logicalVolIntegrityDesc*) malloc(size); integrityDescBlocknumber = blkno; memcpy(lvid, p, size); if( lvid->nextIntegrityExt.extLocation ) { extentLogVolIntegrityDesc = lvid->nextIntegrityExt; blkno = lvid->nextIntegrityExt.extLocation; lastblk = blkno + (lvid->nextIntegrityExt.extLength >> 11); blkno--; /* incremented again in for statement */ } break; default: printf("Unxpected tag %X in Integrity Sequence; blk %d\n", p->descTag.tagIdent, blkno); blkno = lastblk; break; } } if( !lvid || lvid->descTag.tagIdent != TAG_IDENT_LVID ) fail("No Logical Volume Integrity Descriptor\n"); if( medium == CDR && lvid->integrityType == LVID_INTEGRITY_TYPE_CLOSE ) fail("CDR volume has been closed\n"); if( medium == CDR ) // take from VAT FileEntry ((struct logicalVolHeaderDesc*)lvid->logicalVolContentsUse)->uniqueID = CDRuniqueID; curDir = rootDir = (Directory*)malloc(sizeof(Directory)); memset(rootDir, 0, sizeof(Directory)); rootDir->dataSize = 4096; rootDir->data = (uint8_t*)malloc(4096);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -