📄 super.c
字号:
static int udf_remount_fs(struct super_block *sb, int *flags, char *options){ struct udf_options uopt; uopt.flags = UDF_SB(sb)->s_flags; uopt.uid = UDF_SB(sb)->s_uid; uopt.gid = UDF_SB(sb)->s_gid; uopt.umask = UDF_SB(sb)->s_umask; if (!udf_parse_options(options, &uopt)) return -EINVAL; UDF_SB(sb)->s_flags = uopt.flags; UDF_SB(sb)->s_uid = uopt.uid; UDF_SB(sb)->s_gid = uopt.gid; UDF_SB(sb)->s_umask = uopt.umask; if (UDF_SB_LVIDBH(sb)) { int write_rev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev); if (write_rev > UDF_MAX_WRITE_VERSION) *flags |= MS_RDONLY; } if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (*flags & MS_RDONLY) udf_close_lvid(sb); else udf_open_lvid(sb); return 0;}/* * udf_set_blocksize * * PURPOSE * Set the block size to be used in all transfers. * * DESCRIPTION * To allow room for a DMA transfer, it is best to guess big when unsure. * This routine picks 2048 bytes as the blocksize when guessing. This * should be adequate until devices with larger block sizes become common. * * 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 int udf_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 int udf_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) { brelse(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)) { brelse(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; } brelse(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 void udf_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 < ARRAY_SIZE(last); 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); brelse(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); brelse(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); brelse(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); brelse(bh); if (ident == TAG_IDENT_AVDP && location == 256) UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); } } for (i = 0; i < ARRAY_SIZE(UDF_SB_ANCHOR(sb)); 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 { brelse(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, kernel_lb_addr *fileset, kernel_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) { brelse(bh); return 1; } } if (!bh) { /* Search backwards through the partitions */ kernel_lb_addr newfileset;/* --> cvg: FIXME - is it reasonable? */ 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); brelse(bh); break; } case TAG_IDENT_FSD: *fileset = newfileset; break; default: newfileset.logicalBlockNum++; brelse(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); brelse(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))) { kernel_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, kernel_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 int 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) { kernel_lb_addr loc = { .logicalBlockNum = le32_to_cpu(phd->unallocSpaceTable.extPosition), .partitionReferenceNum = i, }; UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = udf_iget(sb, loc); if (!UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table) { udf_debug("cannot load unallocSpaceTable (part %d)\n", i); return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -