📄 super.c
字号:
* Note that the Linux kernel can currently only deal with blocksizes of * 512, 1024, 2048, 4096, and 8192 bytes. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * * POST-CONDITIONS * sb->s_blocksize Blocksize. * sb->s_blocksize_bits log2 of blocksize. * <return> 0 Blocksize is valid. * <return> 1 Blocksize is invalid. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */static intudf_set_blocksize(struct super_block *sb, int bsize){ if (!sb_min_blocksize(sb, bsize)) { udf_debug("Bad block size (%d)\n", bsize); printk(KERN_ERR "udf: bad block size (%d)\n", bsize); return 0; } return sb->s_blocksize;}static intudf_vrs(struct super_block *sb, int silent){ struct volStructDesc *vsd = NULL; int sector = 32768; int sectorsize; struct buffer_head *bh = NULL; int iso9660=0; int nsr02=0; int nsr03=0; /* Block size must be a multiple of 512 */ if (sb->s_blocksize & 511) return 0; if (sb->s_blocksize < sizeof(struct volStructDesc)) sectorsize = sizeof(struct volStructDesc); else sectorsize = sb->s_blocksize; sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits); udf_debug("Starting at sector %u (%ld byte sectors)\n", (sector >> sb->s_blocksize_bits), sb->s_blocksize); /* Process the sequence (if applicable) */ for (;!nsr02 && !nsr03; sector += sectorsize) { /* Read a block */ bh = udf_tread(sb, sector >> sb->s_blocksize_bits); if (!bh) break; /* Look for ISO descriptors */ vsd = (struct volStructDesc *)(bh->b_data + (sector & (sb->s_blocksize - 1))); if (vsd->stdIdent[0] == 0) { udf_release_data(bh); break; } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) { iso9660 = sector; switch (vsd->structType) { case 0: udf_debug("ISO9660 Boot Record found\n"); break; case 1: udf_debug("ISO9660 Primary Volume Descriptor found\n"); break; case 2: udf_debug("ISO9660 Supplementary Volume Descriptor found\n"); break; case 3: udf_debug("ISO9660 Volume Partition Descriptor found\n"); break; case 255: udf_debug("ISO9660 Volume Descriptor Set Terminator found\n"); break; default: udf_debug("ISO9660 VRS (%u) found\n", vsd->structType); break; } } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BEA01, VSD_STD_ID_LEN)) { } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01, VSD_STD_ID_LEN)) { udf_release_data(bh); break; } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN)) { nsr02 = sector; } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, VSD_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_t ident; uint32_t 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 == TAG_IDENT_AVDP) { if (location == last[i] - UDF_SB_SESSION(sb)) { lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb); UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb); } 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_SESSION(sb); UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb); } else udf_debug("Anchor found at block %d, location mismatch %d.\n", last[i], location); } else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE) { lastblock = last[i]; UDF_SB_ANCHOR(sb)[3] = 512; } 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 == TAG_IDENT_AVDP && 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 == TAG_IDENT_AVDP && 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 == TAG_IDENT_AVDP && 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 != TAG_IDENT_AVDP) && (i || (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE))) { 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_t ident; if (fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) { bh = udf_read_ptagged(sb, *fileset, 0, &ident); if (!bh) return 1; else if (ident != TAG_IDENT_FSD) { 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 TAG_IDENT_SBD: { 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 TAG_IDENT_FSD: { *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).tv_sec = recording; UDF_SB_RECORDTIME(sb).tv_nsec = recording_usec * 1000; } 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); if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY) UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY; if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE) UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_WRITE_ONCE; if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_REWRITABLE) UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_REWRITABLE; if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_OVERWRITABLE) UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_OVERWRITABLE; if (!strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) || !strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) { struct partitionHeaderDesc *phd; phd = (struct partitionHeaderDesc *)(p->partitionContentsUse); if (phd->unallocSpaceTable.extLength) { lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.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("unallocSpaceTable (part %d) @ %ld\n", i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); } if (phd->unallocSpaceBitmap.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->unallocSpaceBitmap.extLength); UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition = le32_to_cpu(phd->unallocSpaceBitmap.extPosition); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP; udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -