static PedGeometry* ufs_probe_sun (PedGeometry* geom) { int8_t buf[512 * 3]; struct ufs_super_block *sb; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; if (PED_BE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_LE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
static PedGeometry* xfs_probe (PedGeometry* geom) { PedSector block_size; PedSector block_count; union { struct xfs_sb sb; char bytes [512]; } buf; if (geom->length < XFS_SB_DADDR + 1) return NULL; if (!ped_geometry_read (geom, &buf, XFS_SB_DADDR, 1)) return NULL; if (PED_LE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_LE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_LE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_BE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_BE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_BE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
static int bsd_read (PedDisk* disk) { BSDDiskData* bsd_specific = (BSDDiskData*) disk->disk_specific; BSDRawLabel* label; int i; ped_disk_delete_all (disk); void *s0; if (!ptt_read_sector (disk->dev, 0, &s0)) return 0; memcpy (bsd_specific->boot_code, s0, sizeof (bsd_specific->boot_code)); free (s0); label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET); for (i = 1; i <= BSD_MAXPARTITIONS; i++) { PedPartition* part; BSDPartitionData* bsd_part_data; PedSector start; PedSector end; PedConstraint* constraint_exact; if (!label->d_partitions[i - 1].p_size || !label->d_partitions[i - 1].p_fstype) continue; start = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset); end = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset) + PED_LE32_TO_CPU(label->d_partitions[i - 1].p_size) - 1; part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, start, end); if (!part) goto error; bsd_part_data = part->disk_specific; bsd_part_data->type = label->d_partitions[i - 1].p_fstype; part->num = i; part->fs_type = ped_file_system_probe (&part->geom); constraint_exact = ped_constraint_exact (&part->geom); if (!ped_disk_add_partition (disk, part, constraint_exact)) goto error; ped_constraint_destroy (constraint_exact); } return 1; error: return 0; }
static PedGeometry* jfs_probe (PedGeometry* geom) { union { struct superblock sb; char bytes[512]; } buf; /* FIXME: for now, don't even try to deal with larger sector size. */ if (geom->dev->sector_size != PED_SECTOR_SIZE_DEFAULT) return NULL; if (geom->length < JFS_SUPER_SECTOR + 1) return NULL; if (!ped_geometry_read (geom, &buf, JFS_SUPER_SECTOR, 1)) return NULL; if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) { PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512; PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } else { return NULL; } }
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; }
static PedGeometry* ufs_probe_hp (PedGeometry* geom) { int8_t buf[1536]; struct ufs_super_block *sb; PedSector block_size; PedSector block_count; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; /* Try sane bytesex */ switch (PED_BE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } /* Try perverted bytesex */ switch (PED_LE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
int fat_info_sector_read (FatInfoSector** isp, const PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); int status; PED_ASSERT (isp != NULL); if (!ped_geometry_read_alloc (fs->geom, (void **)isp, fs_info->info_sector_offset, 1)) return 0; FatInfoSector *is = *isp; if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) { status = ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, _("The information sector has the wrong " "signature (%x). Select cancel for now, " "and send in a bug report. If you're " "desperate, it's probably safe to ignore."), PED_LE32_TO_CPU (is->signature_2)); if (status == PED_EXCEPTION_CANCEL) return 0; } return 1; }
static PedGeometry* jfs_probe (PedGeometry* geom) { union { struct superblock sb; char bytes[512]; } buf; if (geom->length < JFS_SUPER_SECTOR + 1) return NULL; if (!ped_geometry_read (geom, &buf, JFS_SUPER_SECTOR, 1)) return NULL; if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) { PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512; PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } else { return NULL; } }
static int bsd_probe (const PedDevice *dev) { BSDRawLabel *partition; PED_ASSERT (dev != NULL); if (dev->sector_size < 512) return 0; void *label; if (!ptt_read_sector (dev, 0, &label)) return 0; partition = (BSDRawLabel *) ((char *) label + BSD_LABEL_OFFSET); alpha_bootblock_checksum(label); /* check magic */ bool found = PED_LE32_TO_CPU (partition->d_magic) == BSD_DISKMAGIC; free (label); return found; }
/* 1 => Success, the journal has been completly replayed, or don't need to */ int hfsj_replay_journal(PedFileSystem* fs) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedSector sector, length; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsJJournalInfoBlock* jib; HfsJJournalHeader* jh; int binsect; uint32_t cksum; binsect = PED_BE32_TO_CPU(priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT; priv_data->jib_start_block = PED_BE32_TO_CPU(priv_data->vh->journal_info_block); sector = (PedSector) priv_data->jib_start_block * binsect; if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) return 0; jib = (HfsJJournalInfoBlock*) buf; if ( (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) && !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { priv_data->jl_start_block = HFS_64_TO_CPU(jib->offset, is_le) / ( PED_SECTOR_SIZE_DEFAULT * binsect ); } if (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_NEED_INIT)) return 1; if ( !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) || (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Journal stored outside of the volume are " "not supported. Try to desactivate the " "journal and run Parted again.")); return 0; } if ( (PED_BE64_TO_CPU(jib->offset) % PED_SECTOR_SIZE_DEFAULT) || (PED_BE64_TO_CPU(jib->size) % PED_SECTOR_SIZE_DEFAULT) ) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Journal offset or size is not multiple of " "the sector size.")); return 0; } sector = PED_BE64_TO_CPU(jib->offset) / PED_SECTOR_SIZE_DEFAULT; length = PED_BE64_TO_CPU(jib->size) / PED_SECTOR_SIZE_DEFAULT; jib = NULL; if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) return 0; jh = (HfsJJournalHeader*) buf; if (jh->endian == PED_LE32_TO_CPU(HFSJ_ENDIAN_MAGIC)) is_le = 1; if ( (jh->magic != HFS_32_TO_CPU(HFSJ_HEADER_MAGIC, is_le)) || (jh->endian != HFS_32_TO_CPU(HFSJ_ENDIAN_MAGIC, is_le)) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Incorrect magic values in the journal header.")); return 0; } if ( (HFS_64_TO_CPU(jh->size, is_le)%PED_SECTOR_SIZE_DEFAULT) || (HFS_64_TO_CPU(jh->size, is_le)/PED_SECTOR_SIZE_DEFAULT != (uint64_t)length) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Journal size mismatch between journal info block " "and journal header.")); return 0; } if ( (HFS_64_TO_CPU(jh->start, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_64_TO_CPU(jh->end, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_32_TO_CPU(jh->blhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_32_TO_CPU(jh->jhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Some header fields are not multiple of the sector " "size.")); return 0; } if (HFS_32_TO_CPU(jh->jhdr_size, is_le) != PED_SECTOR_SIZE_DEFAULT) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The sector size stored in the journal is not 512 " "bytes. Parted only supports 512 bytes length " "sectors.")); return 0; } cksum = HFS_32_TO_CPU(jh->checksum, is_le); jh->checksum = 0; if (cksum != hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh))) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Bad journal checksum.")); return 0; } jh->checksum = HFS_CPU_TO_32(cksum, is_le); /* The 2 following test are in the XNU Darwin source code */ /* so I assume they're needed */ if (jh->start == jh->size) jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); if (jh->end == jh->size) jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); if (jh->start == jh->end) return 1; if (ped_exception_throw ( PED_EXCEPTION_WARNING, PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, _("The journal is not empty. Parted must replay the " "transactions before opening the file system. This will " "modify the file system.")) != PED_EXCEPTION_FIX) return 0; while (jh->start != jh->end) { /* Replay one complete transaction */ if (!hfsj_replay_transaction(fs, jh, sector, length)) return 0; /* Recalculate cksum of the journal header */ jh->checksum = 0; /* need to be 0 while calculating the cksum */ cksum = hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh)); jh->checksum = HFS_CPU_TO_32(cksum, is_le); /* Update the Journal Header */ if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) || !ped_geometry_sync(priv_data->plus_geom)) return 0; } if (hfsj_vh_replayed) { /* probe could have reported incorrect info ! */ /* is there a way to ask parted to quit ? */ ped_exception_throw( PED_EXCEPTION_WARNING, PED_EXCEPTION_OK, _("The volume header or the master directory block has " "changed while replaying the journal. You should " "restart Parted.")); return 0; } return 1; }
uint32_t fat_dir_entry_get_length (FatDirEntry* dir_entry) { return PED_LE32_TO_CPU (dir_entry->length); }
/* 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; }