static int check_partition_consistency (const PedDevice* dev, const PC98RawPartition* raw_part) { if (raw_part->ipl_sect >= dev->hw_geom.sectors || raw_part->sector >= dev->hw_geom.sectors || raw_part->end_sector >= dev->hw_geom.sectors || raw_part->ipl_head >= dev->hw_geom.heads || raw_part->head >= dev->hw_geom.heads || raw_part->end_head >= dev->hw_geom.heads || PED_LE16_TO_CPU(raw_part->ipl_cyl) >= dev->hw_geom.cylinders || PED_LE16_TO_CPU(raw_part->cyl) >= dev->hw_geom.cylinders || PED_LE16_TO_CPU(raw_part->end_cyl) >= dev->hw_geom.cylinders || PED_LE16_TO_CPU(raw_part->cyl) > PED_LE16_TO_CPU(raw_part->end_cyl) #if 0 || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->ipl_cyl), raw_part->ipl_head, raw_part->ipl_sect) || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->cyl), raw_part->head, raw_part->sector) || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->end_cyl), raw_part->end_head, raw_part->end_sector) #endif || PED_LE16_TO_CPU(raw_part->end_cyl) < PED_LE16_TO_CPU(raw_part->cyl)) return 0; return 1; }
/* Reads in the boot sector (superblock), and does a minimum of sanity * checking. The goals are: * - to detect fat file systems, even if they are damaged [i.e. not * return an error / throw an exception] * - to fail detection if there's not enough information for * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero) */ int fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom) { PED_ASSERT (bs != NULL); PED_ASSERT (geom != NULL); if (!ped_geometry_read (geom, bs, 0, 1)) return 0; if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid signature for a FAT " "file system.")); return 0; } if (!bs->system_id[0]) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid signature for a FAT " "file system.")); return 0; } if (!bs->sector_size || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid sector size for a FAT " "file system.")); return 0; } if (!bs->cluster_size) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid cluster size for a FAT " "file system.")); return 0; } if (!bs->reserved) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid number of reserved " "sectors for a FAT file system.")); return 0; } if (bs->fats < 1 || bs->fats > 4) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid number of FATs.")); return 0; } return 1; }
static int is_unused_partition(const PC98RawPartition* raw_part) { if (raw_part->mid || raw_part->sid || raw_part->ipl_sect || raw_part->ipl_head || PED_LE16_TO_CPU(raw_part->ipl_cyl) || raw_part->sector || raw_part->head || PED_LE16_TO_CPU(raw_part->cyl) || raw_part->end_sector || raw_part->end_head || PED_LE16_TO_CPU(raw_part->end_cyl)) return 0; return 1; }
static PedGeometry *reiserfs_probe(PedGeometry *geom) { int i; reiserfs_super_block_t sb; PED_ASSERT(geom != NULL); for (i = 0; reiserfs_super_offset[i] != -1; i++) { if (reiserfs_super_offset[i] >= geom->length) continue; if (!ped_geometry_read (geom, &sb, reiserfs_super_offset[i], 1)) continue; if (strncmp(REISERFS_SIGNATURE, sb.s_magic, strlen(REISERFS_SIGNATURE)) == 0 || strncmp(REISER2FS_SIGNATURE, sb.s_magic, strlen(REISER2FS_SIGNATURE)) == 0 || strncmp(REISER3FS_SIGNATURE, sb.s_magic, strlen(REISER3FS_SIGNATURE)) == 0) { PedSector block_size; PedSector block_count; block_size = PED_LE16_TO_CPU(sb.s_blocksize) / PED_SECTOR_SIZE_DEFAULT; block_count = PED_LE32_TO_CPU(sb.s_block_count); return ped_geometry_new(geom->dev, geom->start, block_size * block_count); } } return NULL; }
FatCluster fat_dir_entry_get_first_cluster (FatDirEntry* dir_entry, PedFileSystem *fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); switch (fs_info->fat_type) { case FAT_TYPE_FAT12: case FAT_TYPE_FAT16: return PED_LE16_TO_CPU (dir_entry->first_cluster); case FAT_TYPE_FAT32: return PED_LE16_TO_CPU (dir_entry->first_cluster_high) * 65536L + PED_LE16_TO_CPU (dir_entry->first_cluster); } return 0; }
static PedSector _GL_ATTRIBUTE_PURE legacy_end (const PedDisk* disk, const PC98RawPartition* raw_part) { PED_ASSERT (disk != NULL); PED_ASSERT (raw_part != NULL); if (raw_part->end_head == 0 && raw_part->end_sector == 0) { return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->end_cyl), disk->dev->hw_geom.heads - 1, disk->dev->hw_geom.sectors - 1); } else { return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->end_cyl), raw_part->end_head, raw_part->end_sector); } }
static PedSector _GL_ATTRIBUTE_PURE legacy_start (const PedDisk* disk, const PC98RawPartition* raw_part) { PED_ASSERT (disk != NULL); PED_ASSERT (raw_part != NULL); return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->cyl), raw_part->head, raw_part->sector); }
/* magic(?) check */ static int pc98_check_magic (const PC98RawTable *part_table) { /* check "extended-format" (have partition table?) */ if (PED_LE16_TO_CPU(part_table->magic) != PC9800_EXTFMT_MAGIC) return 0; return 1; }
/* XXX fixme: endian? */ static unsigned short xbsd_dkcksum (BSDRawLabel *lp) { unsigned short *start, *end; unsigned short sum = 0; lp->d_checksum = 0; start = (u_short*) lp; end = (u_short*) &lp->d_partitions [ PED_LE16_TO_CPU (lp->d_npartitions)]; while (start < end) sum ^= *start++; return sum; }
/* Don't trust the FAT12, FAT16 or FAT32 label string. */ FatType fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom) { PedSector logical_sector_size; PedSector first_cluster_sector; FatCluster cluster_count; if (!PED_LE16_TO_CPU (bs->dir_entries)) return FAT_TYPE_FAT32; logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512; first_cluster_sector = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size + PED_LE16_TO_CPU (bs->dir_entries) / (512 / sizeof (FatDirEntry)); cluster_count = (geom->length - first_cluster_sector) / bs->cluster_size / logical_sector_size; if (cluster_count > MAX_FAT12_CLUSTERS) return FAT_TYPE_FAT16; else return FAT_TYPE_FAT12; }
/* Analyses the boot sector, and sticks appropriate numbers in fs->type_specific. Note: you need to subtract (2 * cluster_sectors) off cluster offset, because the first cluster is number 2. (0 and 1 are not real clusters, and referencing them is a bug) */ int fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); int fat_entry_size; PED_ASSERT (bs != NULL); fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512; fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track); fs_info->heads = PED_LE16_TO_CPU (bs->heads); if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63 || fs_info->heads < 1 || fs_info->heads > 255) { PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom; int cyl_count = 0; if (fs_info->heads > 0 && fs_info->sectors_per_track > 0) cyl_count = fs->geom->dev->length / fs_info->heads / fs_info->sectors_per_track; switch (ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE + PED_EXCEPTION_CANCEL, _("The file system's CHS geometry is (%d, %d, %d), " "which is invalid. The partition table's CHS " "geometry is (%d, %d, %d). If you select Ignore, " "the file system's CHS geometry will be left " "unchanged. If you select Fix, the file system's " "CHS geometry will be set to match the partition " "table's CHS geometry."), cyl_count, fs_info->heads, fs_info->sectors_per_track, bios_geom->cylinders, bios_geom->heads, bios_geom->sectors)) { case PED_EXCEPTION_FIX: fs_info->sectors_per_track = bios_geom->sectors; fs_info->heads = bios_geom->heads; bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track); bs->heads = PED_CPU_TO_LE16 (fs_info->heads); if (!fat_boot_sector_write (bs, fs)) return 0; break; case PED_EXCEPTION_CANCEL: return 0; case PED_EXCEPTION_IGNORE: break; default: break; } } if (bs->sectors) fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors) * fs_info->logical_sector_size; else fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count) * fs_info->logical_sector_size; fs_info->fat_table_count = bs->fats; fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries); fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved) * fs_info->logical_sector_size; fs_info->cluster_sectors = bs->cluster_size * fs_info->logical_sector_size; fs_info->cluster_size = fs_info->cluster_sectors * 512; if (fs_info->logical_sector_size == 0) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("FAT boot sector says logical sector size is 0. " "This is weird. ")); return 0; } if (fs_info->fat_table_count == 0) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("FAT boot sector says there are no FAT tables. This " "is weird. ")); return 0; } if (fs_info->cluster_sectors == 0) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("FAT boot sector says clusters are 0 sectors. This " "is weird. ")); return 0; } fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom); if (fs_info->fat_type == FAT_TYPE_FAT12) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("File system is FAT12, which is unsupported.")); return 0; } if (fs_info->fat_type == FAT_TYPE_FAT16) { fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length) * fs_info->logical_sector_size; fs_info->serial_number = PED_LE32_TO_CPU (bs->u.fat16.serial_number); fs_info->root_cluster = 0; fs_info->root_dir_offset = fs_info->fat_offset + fs_info->fat_sectors * fs_info->fat_table_count; fs_info->root_dir_sector_count = fs_info->root_dir_entry_count * sizeof (FatDirEntry) / (512 * fs_info->logical_sector_size); fs_info->cluster_offset = fs_info->root_dir_offset + fs_info->root_dir_sector_count; } if (fs_info->fat_type == FAT_TYPE_FAT32) { fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length) * fs_info->logical_sector_size; fs_info->serial_number = PED_LE32_TO_CPU (bs->u.fat32.serial_number); fs_info->info_sector_offset = PED_LE16_TO_CPU (fs_info->boot_sector->u.fat32.info_sector) * fs_info->logical_sector_size; fs_info->boot_sector_backup_offset = PED_LE16_TO_CPU (fs_info->boot_sector->u.fat32.backup_sector) * fs_info->logical_sector_size; fs_info->root_cluster = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster); fs_info->root_dir_offset = 0; fs_info->root_dir_sector_count = 0; fs_info->cluster_offset = fs_info->fat_offset + fs_info->fat_sectors * fs_info->fat_table_count; } fs_info->cluster_count = (fs_info->sector_count - fs_info->cluster_offset) / fs_info->cluster_sectors; fat_entry_size = fat_table_entry_size (fs_info->fat_type); if (fs_info->cluster_count + 2 > fs_info->fat_sectors * 512 / fat_entry_size) fs_info->cluster_count = fs_info->fat_sectors * 512 / fat_entry_size - 2; fs_info->dir_entries_per_cluster = fs_info->cluster_size / sizeof (FatDirEntry); return 1; }
static int read_table (PedDisk* disk) { int i; PC98RawTable table; PedConstraint* constraint_any; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); constraint_any = ped_constraint_any (disk->dev); if (!ped_device_read (disk->dev, (void*) &table, 0, 2)) goto error; if (!pc98_check_magic(&table)) { if (ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, _("Invalid partition table on %s."), disk->dev->path)) goto error; } for (i = 0; i < MAX_PART_COUNT; i++) { PC98RawPartition* raw_part; PedPartition* part; PC98PartitionData* pc98_data; PedSector part_start; PedSector part_end; raw_part = &table.partitions [i]; if (is_unused_partition(raw_part)) continue; part_start = legacy_start (disk, raw_part); part_end = legacy_end (disk, raw_part); part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, part_start, part_end); if (!part) goto error; pc98_data = part->disk_specific; PED_ASSERT (pc98_data != NULL); pc98_data->system = (raw_part->mid << 8) | raw_part->sid; pc98_data->boot = GET_BIT(raw_part->mid, 7); pc98_data->hidden = !GET_BIT(raw_part->sid, 7); ped_partition_set_name (part, raw_part->name); pc98_data->ipl_sector = chs_to_sector ( disk->dev, PED_LE16_TO_CPU(raw_part->ipl_cyl), raw_part->ipl_head, raw_part->ipl_sect); /* hack */ if (pc98_data->ipl_sector == part->geom.start) pc98_data->ipl_sector = 0; part->num = i + 1; if (!ped_disk_add_partition (disk, part, constraint_any)) goto error; if (part->geom.start != part_start || part->geom.end != part_end) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Partition %d isn't aligned to cylinder " "boundaries. This is still unsupported."), part->num); goto error; } part->fs_type = ped_file_system_probe (&part->geom); } ped_constraint_destroy (constraint_any); return 1; error: ped_disk_delete_all (disk); ped_constraint_destroy (constraint_any); return 0; }