📄 wrudf-cmnd.c
字号:
* irrespective whether they were embedded or separately in allocated extents. * updateDirectory() will embed or write in separate extents as appropriate. */Directory * readDirectory(Directory *parentDir, long_ad* icb, char *name) { char *p; uint32_t len; Directory *dir; if( parentDir == NULL ) dir = rootDir; else { dir = parentDir->child; if( dir == NULL ) { parentDir->child = dir = (Directory*)malloc(sizeof(Directory)); memset(dir, 0, sizeof(Directory)); dir->parent = parentDir; dir->dataSize = 4096; dir->data = (uint8_t*)malloc(4096); if( dir->name ) free(dir->name); dir->name = malloc(strlen(name) + 1); strcpy(dir->name, name); } else if( dir->icb.extLocation.logicalBlockNum == icb->extLocation.logicalBlockNum && dir->icb.extLocation.partitionReferenceNum == icb->extLocation.partitionReferenceNum ) return dir; // already the one requested } if( dir->dirDirty ) updateDirectory(dir); dir->icb = *icb; if( name[0] ) { if( dir->name ) free(dir->name); dir->name = malloc(strlen(name) + 1); strcpy(dir->name, name); } p = readTaggedBlock(icb->extLocation.logicalBlockNum, icb->extLocation.partitionReferenceNum); memcpy(&dir->fe, p, 2048); if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB ) { memcpy(dir->data, dir->fe.allocDescs + dir->fe.lengthExtendedAttr, dir->fe.lengthAllocDescs); memset(dir->fe.allocDescs + dir->fe.lengthExtendedAttr, 0, dir->fe.lengthAllocDescs); } else { if( dir->fe.informationLength > dir->dataSize ) { len = (dir->fe.informationLength + 2047) & ~2047; dir->data = realloc(dir->data, len); if( !dir->data ) { printf("Realloc directory data failed\n"); return NULL; } dir->dataSize = len; } readExtents(dir->data, (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT, dir->fe.allocDescs + dir->fe.lengthExtendedAttr); if( medium == CDRW ) { if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT ) freeShortExtents((short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); else if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG ) freeLongExtents((long_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); } } printf("Read dir %s\n", dir->name); return dir;}/* updateDirectory() * Extents and ICB AllocMask are unchanged since reading the directory from CD. * Based on current informationLength will have to decide embedding or on output extents required * and free any superfluous extents */int updateDirectory(Directory* dir) { int i; struct fileIdentDesc *fid; if( dir->child ) updateDirectory(dir->child); if( !dir->dirDirty ) return CMND_OK; if( sizeof(struct fileEntry) + dir->fe.lengthExtendedAttr + dir->fe.informationLength <= 2048 ) { /* fileIdentDescs embedded in directory ICB */ dir->fe.logicalBlocksRecorded = 0; dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_IN_ICB; dir->fe.lengthAllocDescs = dir->fe.informationLength; memcpy(dir->fe.allocDescs + dir->fe.lengthExtendedAttr, dir->data, dir->fe.lengthAllocDescs); /* UDF2.00 2.2.1.3 - For a structure in virtual space, tagLocation is the virtual location */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->fe.allocDescs + i); fid->descTag.tagLocation = dir->icb.extLocation.logicalBlockNum; setChecksum(&fid->descTag); } } else { /* get new extents for the directory data */ dir->fe.logicalBlocksRecorded = ((dir->fe.informationLength + 2047) & ~2047) >> 11; if( medium == CDR ) { long_ad *ad; uint32_t blkno; dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_LONG; ad = (long_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr); ad->extLength = dir->fe.informationLength; ad->extLocation.logicalBlockNum = blkno = getNWA() + 1 - pd->partitionStartingLocation; ad->extLocation.partitionReferenceNum = pd->partitionNumber; *(uint32_t*)&((struct allocDescImpUse*)(ad->impUse))->impUse = (uint32_t) dir->fe.uniqueID; memset(ad + 1, 0, sizeof(long_ad)); /* necessary only if infolength multiple of 2048 */ dir->fe.lengthAllocDescs = 2 * sizeof(long_ad); /* set tagLocation in all FIDs */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->data + i); fid->descTag.tagLocation = blkno + (i >> 11); fid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) - sizeof(tag); setChecksum(fid); } } else { uint32_t *blocks, blkno, len; short_ad *extent; extent =(short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr); dir->fe.lengthAllocDescs = getExtents(dir->fe.informationLength, extent); dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_SHORT; /* find which blocks are to going be used to set tagLocations */ blocks = (uint32_t*)malloc(dir->fe.logicalBlocksRecorded * sizeof(uint32_t)); blkno = extent->extPosition; len = extent->extLength; for( i = 0; i < dir->fe.logicalBlocksRecorded; i++ ) { blocks[i] = blkno; if( len <= 2048 ) { extent++; blkno = extent->extPosition; len = extent->extLength; } else { len -= 2048; blkno++; } } /* set tagLocation */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->data + i); fid->descTag.tagLocation = blocks[i >> 11]; fid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) - sizeof(tag); setChecksum(fid); } free(blocks); } } dir->fe.descTag.descCRCLength = sizeof(struct fileEntry) + dir->fe.lengthExtendedAttr + dir->fe.lengthAllocDescs - sizeof(tag); setChecksum(&dir->fe); if( medium == CDRW ) { /* write the directory fileEntry */ writeBlock(dir->icb.extLocation.logicalBlockNum, dir->icb.extLocation.partitionReferenceNum, &dir->fe); if( dir->fe.logicalBlocksRecorded ) { /* write any directory data */ writeExtents(dir->data, 1, (short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); } } else { /* medium == CDR */ int retries; retries = 0; for( ;; ) { /* loop only when verify failed */ uint32_t pbn; /* write the directory fileEntry */ pbn = writeCDR(&dir->fe); vat[((long_ad*)&dir->icb)->extLocation.logicalBlockNum] = pbn - pd->partitionStartingLocation; if( dir->fe.logicalBlocksRecorded ) for( i = 0; i < dir->fe.informationLength; i += 2048 ) writeCDR(dir->data + i); if( verifyCDR(&dir->fe) == 0 ) break; if( ++retries > 3 ) { printf("updateDirectory: '%s' failed\n", dir->name); return CMND_FAILED; } } } dir->dirDirty = 0; printf("Wrote dir %s\n", dir->name); return CMND_OK;}/* Create subdirectory called 'name' in 'dir' */Directory * makeDir(Directory *dir, char* name ) { int rv; Directory *newDir; struct fileEntry *fe; struct fileIdentDesc *backFid, *forwFid; short_ad allocDescs[2]; /* back reference to parent in new directory */ backFid = makeFileIdentDesc(""); backFid->icb = dir->icb; backFid->fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; backFid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + 3) & ~3) - sizeof(tag); fe = makeFileEntry(); fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY; fe->icbTag.flags = ICBTAG_FLAG_AD_IN_ICB; fe->informationLength = (sizeof(struct fileIdentDesc) + 3) & ~3; /* forward reference to new directory in parent directory */ forwFid = makeFileIdentDesc(name); forwFid->fileCharacteristics = FID_FILE_CHAR_DIRECTORY; *(uint32_t*)(&( (struct allocDescImpUse*)forwFid->icb.impUse)->impUse) = (uint32_t) fe->uniqueID; if( medium == CDR ) { fe->descTag.tagLocation = newVATentry(); forwFid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation; forwFid->icb.extLocation.partitionReferenceNum = virtualPartitionNum; } else { if( getExtents( 2048, allocDescs) != 16 ) fail("makeDir: Could not get File Entry extent\n"); markBlock(ALLOC, allocDescs[0].extPosition); fe->descTag.tagLocation = allocDescs[0].extPosition; backFid->descTag.tagLocation = allocDescs[0].extPosition; forwFid->icb.extLocation.logicalBlockNum = allocDescs[0].extPosition; forwFid->icb.extLocation.partitionReferenceNum = pd->partitionNumber; setChecksum(&backFid->descTag); fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthAllocDescs - sizeof(tag); setChecksum(fe); } rv = insertFileIdentDesc(dir, forwFid); dir->fe.fileLinkCount++; dir->dirDirty = 1; /* setup directory structure for new directory */ newDir = dir->child; if( newDir != NULL ) updateDirectory(newDir); else { newDir = (Directory*)malloc(sizeof(Directory)); memset(newDir, 0, sizeof(Directory)); newDir->parent = dir; newDir->dataSize = 4096; newDir->data = (uint8_t*)malloc(4096); dir->child = newDir; } memset(newDir->data, 0, newDir->dataSize); newDir->name = malloc(strlen(name)+1); strcpy(newDir->name, name); newDir->icb = forwFid->icb; memcpy(&newDir->fe, fe, 2048); memcpy(newDir->data, backFid, fe->informationLength); newDir->dirDirty = 1; ((struct logicalVolIntegrityDescImpUse*) (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions))->numDirs++; free(backFid); free(forwFid); free(fe); return newDir;}/* analyzeDest() * * The last argument in a command is the destination for copying or the object * to act on. The argument consists of / separated components * eg. /src/test/udf/wrudf.h or /src/test/iso/ * or just a single component eg. . or / or wrudf.c * * All but the last component must be existing directories and curDir points to * the last directopry in that chain, eg. udf, otherwise result DIR_INVALID. * * When the last component does not exist, return result DOES_NOT_EXIST. * name --> last component eg. wrudf.h or iso * * If the last component identifies a directory return EXISTING_DIR or DELETED_DIR, * *fid = NULL, *name = last component name eg. iso. * * If the last component is a file return EXISTING_FILE or DELETED_FILE. * *fid points to FID entry in curDir with name equal the last component. * *name --> last component name eg. wrudf.h */enum RV analyzeDest(char* arg, struct fileIdentDesc** fid, char** name) { int len; char *comp, *endComp; if( arg[0] == '/' ) { curDir = rootDir; comp = arg + 1; } else { comp = arg; } len = strlen(comp); if( len > 1 && comp[len-1] == '/' ) comp[len-1] = 0; /* remove any trailing slash */ for( ; ( endComp = strchr(comp, '/') ) != NULL; comp = ++endComp ) { *endComp = 0; if( strcmp(comp, ".") == 0 ) continue; if( strcmp(comp, "..") == 0 ) { if( !curDir->parent ) return DIR_INVALID; curDir = curDir->parent; continue; } *fid = findFileIdentDesc(curDir, comp); if( *fid == NULL ) return DIR_INVALID; if( ! (*fid)->fileCharacteristics & FID_FILE_CHAR_DIRECTORY ) return DIR_INVALID; if( (*fid)->fileCharacteristics & FID_FILE_CHAR_DELETED ) return DIR_INVALID;// curDir = readDirectory(curDir->child, &(*fid)->icb, comp); curDir = readDirectory(curDir, &(*fid)->icb, comp); } // final component *name = comp; if( comp[0] == 0 || strcmp(comp, ".") == 0 ) return EXISTING_DIR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -