📄 super.c
字号:
{ } else if (!strncmp(vsd->stdIdent, STD_ID_TEA01, STD_ID_LEN)) { udf_release_data(bh); break; } else if (!strncmp(vsd->stdIdent, STD_ID_NSR02, STD_ID_LEN)) { nsr02 = sector; } else if (!strncmp(vsd->stdIdent, STD_ID_NSR03, STD_ID_LEN)) { nsr03 = sector; } udf_release_data(bh); } if (nsr03) return nsr03; else if (nsr02) return nsr02; else if (sector - (UDF_SB_SESSION(sb) << sb->s_blocksize_bits) == 32768) return -1; else return 0;}/* * udf_find_anchor * * PURPOSE * Find an anchor volume descriptor. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * lastblock Last block on media. * * POST-CONDITIONS * <return> 1 if not found, 0 if ok * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */static voidudf_find_anchor(struct super_block *sb){ int lastblock = UDF_SB_LASTBLOCK(sb); struct buffer_head *bh = NULL; Uint16 ident; Uint32 location; int i; if (lastblock) { int varlastblock = udf_variable_to_fixed(lastblock); int last[] = { lastblock, lastblock - 2, lastblock - 150, lastblock - 152, varlastblock, varlastblock - 2, varlastblock - 150, varlastblock - 152 }; lastblock = 0; /* Search for an anchor volume descriptor pointer */ /* according to spec, anchor is in either: * block 256 * lastblock-256 * lastblock * however, if the disc isn't closed, it could be 512 */ for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++) { if (last[i] < 0 || !(bh = sb_bread(sb, last[i]))) { ident = location = 0; } else { ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); udf_release_data(bh); } if (ident == TID_ANCHOR_VOL_DESC_PTR) { if (location == last[i] - UDF_SB_SESSION(sb)) { lastblock = UDF_SB_ANCHOR(sb)[0] = last[i]; UDF_SB_ANCHOR(sb)[1] = last[i] - 256; } else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb)) { UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]); UDF_SB_ANCHOR(sb)[1] = lastblock - 256; } else udf_debug("Anchor found at block %d, location mismatch %d.\n", last[i], location); } else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY) { lastblock = last[i]; UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb); } else { if (last[i] < 256 || !(bh = sb_bread(sb, last[i] - 256))) { ident = location = 0; } else { ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); udf_release_data(bh); } if (ident == TID_ANCHOR_VOL_DESC_PTR && location == last[i] - 256 - UDF_SB_SESSION(sb)) { lastblock = last[i]; UDF_SB_ANCHOR(sb)[1] = last[i] - 256; } else { if (last[i] < 312 + UDF_SB_SESSION(sb) || !(bh = sb_bread(sb, last[i] - 312 - UDF_SB_SESSION(sb)))) { ident = location = 0; } else { ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); udf_release_data(bh); } if (ident == TID_ANCHOR_VOL_DESC_PTR && location == udf_variable_to_fixed(last[i]) - 256) { UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); lastblock = udf_variable_to_fixed(last[i]); UDF_SB_ANCHOR(sb)[1] = lastblock - 256; } } } } } if (!lastblock) { /* We havn't found the lastblock. check 312 */ if ((bh = sb_bread(sb, 312 + UDF_SB_SESSION(sb)))) { ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); udf_release_data(bh); if (ident == TID_ANCHOR_VOL_DESC_PTR && location == 256) UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); } } for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++) { if (UDF_SB_ANCHOR(sb)[i]) { if (!(bh = udf_read_tagged(sb, UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i], &ident))) { UDF_SB_ANCHOR(sb)[i] = 0; } else { udf_release_data(bh); if ((ident != TID_ANCHOR_VOL_DESC_PTR) && (i || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))) { UDF_SB_ANCHOR(sb)[i] = 0; } } } } UDF_SB_LASTBLOCK(sb) = lastblock;}static int udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root){ struct buffer_head *bh = NULL; long lastblock; Uint16 ident; if (fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) { bh = udf_read_ptagged(sb, *fileset, 0, &ident); if (!bh) return 1; else if (ident != TID_FILE_SET_DESC) { udf_release_data(bh); return 1; } } if (!bh) /* Search backwards through the partitions */ { lb_addr newfileset; return 1; for (newfileset.partitionReferenceNum=UDF_SB_NUMPARTS(sb)-1; (newfileset.partitionReferenceNum != 0xFFFF && fileset->logicalBlockNum == 0xFFFFFFFF && fileset->partitionReferenceNum == 0xFFFF); newfileset.partitionReferenceNum--) { lastblock = UDF_SB_PARTLEN(sb, newfileset.partitionReferenceNum); newfileset.logicalBlockNum = 0; do { bh = udf_read_ptagged(sb, newfileset, 0, &ident); if (!bh) { newfileset.logicalBlockNum ++; continue; } switch (ident) { case TID_SPACE_BITMAP_DESC: { struct SpaceBitmapDesc *sp; sp = (struct SpaceBitmapDesc *)bh->b_data; newfileset.logicalBlockNum += 1 + ((le32_to_cpu(sp->numOfBytes) + sizeof(struct SpaceBitmapDesc) - 1) >> sb->s_blocksize_bits); udf_release_data(bh); break; } case TID_FILE_SET_DESC: { *fileset = newfileset; break; } default: { newfileset.logicalBlockNum ++; udf_release_data(bh); bh = NULL; break; } } } while (newfileset.logicalBlockNum < lastblock && fileset->logicalBlockNum == 0xFFFFFFFF && fileset->partitionReferenceNum == 0xFFFF); } } if ((fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) && bh) { udf_debug("Fileset at block=%d, partition=%d\n", fileset->logicalBlockNum, fileset->partitionReferenceNum); UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum; udf_load_fileset(sb, bh, root); udf_release_data(bh); return 0; } return 1;}static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh){ struct PrimaryVolDesc *pvoldesc; time_t recording; long recording_usec; struct ustr instr; struct ustr outstr; pvoldesc = (struct PrimaryVolDesc *)bh->b_data; if ( udf_stamp_to_time(&recording, &recording_usec, lets_to_cpu(pvoldesc->recordingDateAndTime)) ) { timestamp ts; ts = lets_to_cpu(pvoldesc->recordingDateAndTime); udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n", recording, recording_usec, ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone); UDF_SB_RECORDTIME(sb) = recording; } if ( !udf_build_ustr(&instr, pvoldesc->volIdent, 32) ) { if (udf_CS0toUTF8(&outstr, &instr)) { strncpy( UDF_SB_VOLIDENT(sb), outstr.u_name, outstr.u_len > 31 ? 31 : outstr.u_len); udf_debug("volIdent[] = '%s'\n", UDF_SB_VOLIDENT(sb)); } } if ( !udf_build_ustr(&instr, pvoldesc->volSetIdent, 128) ) { if (udf_CS0toUTF8(&outstr, &instr)) udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); }}static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root){ struct FileSetDesc *fset; fset = (struct FileSetDesc *)bh->b_data; *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation); UDF_SB_SERIALNUM(sb) = le16_to_cpu(fset->descTag.tagSerialNum); udf_debug("Rootdir at block=%d, partition=%d\n", root->logicalBlockNum, root->partitionReferenceNum);}static void udf_load_partdesc(struct super_block *sb, struct buffer_head *bh){ struct PartitionDesc *p; int i; p = (struct PartitionDesc *)bh->b_data; for (i=0; i<UDF_SB_NUMPARTS(sb); i++) { udf_debug("Searching map: (%d == %d)\n", UDF_SB_PARTMAPS(sb)[i].s_partition_num, le16_to_cpu(p->partitionNumber)); if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber)) { UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */ UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb); if (!strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR02) || !strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR03)) { struct PartitionHeaderDesc *phd; phd = (struct PartitionHeaderDesc *)(p->partitionContentsUse); if (phd->unallocatedSpaceTable.extLength) { lb_addr loc = { le32_to_cpu(phd->unallocatedSpaceTable.extPosition), i }; UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = udf_iget(sb, loc); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE; udf_debug("unallocatedSpaceTable (part %d) @ %ld\n", i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); } if (phd->unallocatedSpaceBitmap.extLength) { UDF_SB_ALLOC_BITMAP(sb, i, s_uspace); if (UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap != NULL) { UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extLength = le32_to_cpu(phd->unallocatedSpaceBitmap.extLength); UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition = le32_to_cpu(phd->unallocatedSpaceBitmap.extPosition); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP; udf_debug("unallocatedSpaceBitmap (part %d) @ %d\n", i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition); } } if (phd->partitionIntegrityTable.extLength) udf_debug("partitionIntegrityTable (part %d)\n", i); if (phd->freedSpaceTable.extLength) { lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i }; UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table = udf_iget(sb, loc); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE; udf_debug("freedSpaceTable (part %d) @ %ld\n", i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino); } if (phd->freedSpaceBitmap.extLength) { UDF_SB_ALLOC_BITMAP(sb, i, s_fspace); if (UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap != NULL) { UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extLength = le32_to_cpu(phd->freedSpaceBitmap.extLength); UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition = le32_to_cpu(phd->freedSpaceBitmap.extPosition); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_BITMAP; udf_debug("freedSpaceBitmap (part %d) @ %d\n", i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition); } } } break; } } if (i == UDF_SB_NUMPARTS(sb)) { udf_debug("Partition (%d) not found in partition map\n", le16_to_cpu(p->partitionNumber)); } else { udf_debug("Partition (%d:%d type %x) starts at physical %d, block length %d\n", le16_to_cpu(p->partitionNumber), i, UDF_SB_PARTTYPE(sb,i), UDF_SB_PARTROOT(sb,i), UDF_SB_PARTLEN(sb,i)); }}static int udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset){ struct LogicalVolDesc *lvd; int i, j, offset; Uint8 type; lvd = (struct LogicalVolDesc *)bh->b_data; UDF_SB_ALLOC_PARTMAPS(sb, le32_to_cpu(lvd->numPartitionMaps)); for (i=0,offset=0; i<UDF_SB_NUMPARTS(sb) && offset<le32_to_cpu(lvd->mapTableLength); i++,offset+=((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapLength) { type = ((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapType; if (type == 1) { struct GenericPartitionMap1 *gpm1 = (struct GenericPartitionMap1 *)&(lvd->partitionMaps[offset]); UDF_SB_PARTTYPE(sb,i) = UDF_TYPE1_MAP15; UDF_SB_PARTVSN(sb,i) = le16_to_cpu(gpm1->volSeqNum); UDF_SB_PARTNUM(sb,i) = le16_to_cpu(gpm1->partitionNum); UDF_SB_PARTFUNC(sb,i) = NULL; } else if (type == 2) { struct UdfPartitionMap2 *upm2 = (struct UdfPartitionMap2 *)&(lvd->partitionMaps[offset]); if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -