1N/A/*
1N/A libparted - a library for manipulating disk partitions
1N/A Copyright (C) 2001-2002, 2005, 2007-2010 Free Software Foundation,
1N/A Inc.
1N/A
1N/A This program is free software; you can redistribute it and/or modify
1N/A it under the terms of the GNU General Public License as published by
1N/A the Free Software Foundation; either version 3 of the License, or
1N/A (at your option) any later version.
1N/A
1N/A This program is distributed in the hope that it will be useful,
1N/A but WITHOUT ANY WARRANTY; without even the implied warranty of
1N/A MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1N/A GNU General Public License for more details.
1N/A
1N/A You should have received a copy of the GNU General Public License
1N/A along with this program. If not, see <http://www.gnu.org/licenses/>.
1N/A*/
1N/A
1N/A#include <config.h>
1N/A#include <parted/parted.h>
1N/A#include <parted/debug.h>
1N/A#include <parted/endian.h>
1N/A#include <stdbool.h>
1N/A
1N/A#include "dvh.h"
1N/A#include "pt-tools.h"
1N/A
1N/A#if ENABLE_NLS
1N/A# include <libintl.h>
1N/A# define _(String) dgettext (PACKAGE, String)
1N/A#else
1N/A# define _(String) (String)
1N/A#endif /* ENABLE_NLS */
1N/A
1N/A/* Default size for volhdr part, same val as IRIX's fx uses */
1N/A#define PTYPE_VOLHDR_DFLTSZ 4096
1N/A
1N/A/* Partition numbers that seem to be strongly held convention */
1N/A#define PNUM_VOLHDR 8
1N/A#define PNUM_VOLUME 10
1N/A
1N/A/* Other notes of interest:
1N/A * PED_PARTITION_EXTENDED is used for volume headers
1N/A * PED_PARTITION_LOGICAL is used for bootfiles
1N/A * PED_PARTITION_NORMAL is used for all else
1N/A */
1N/A
1N/Atypedef struct _DVHDiskData {
1N/A struct device_parameters dev_params;
1N/A int swap; /* part num of swap, 0=none */
1N/A int root; /* part num of root, 0=none */
1N/A int boot; /* part num of boot, 0=none */
1N/A} DVHDiskData;
1N/A
1N/Atypedef struct _DVHPartData {
1N/A int type;
1N/A char name[VDNAMESIZE + 1]; /* boot volumes only */
1N/A int real_file_size; /* boot volumes only */
1N/A} DVHPartData;
1N/A
1N/Astatic PedDiskType dvh_disk_type;
1N/A
1N/A/* FIXME: factor out this function: copied from aix.c, with changes to
1N/A the description, and an added sector number argument.
1N/A Read sector, SECTOR_NUM (which has length DEV->sector_size) into malloc'd
1N/A storage. If the read fails, free the memory and return zero without
1N/A modifying *BUF. Otherwise, set *BUF to the new buffer and return 1. */
1N/Astatic int
1N/Aread_sector (const PedDevice *dev, PedSector sector_num, char **buf)
1N/A{
1N/A char *b = ped_malloc (dev->sector_size);
1N/A PED_ASSERT (b != NULL, return 0);
1N/A if (!ped_device_read (dev, b, sector_num, 1)) {
1N/A free (b);
1N/A return 0;
1N/A }
1N/A *buf = b;
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Advh_probe (const PedDevice *dev)
1N/A{
1N/A struct volume_header *vh;
1N/A
1N/A char *label;
1N/A if (!read_sector (dev, 0, &label))
1N/A return 0;
1N/A
1N/A vh = (struct volume_header *) label;
1N/A
1N/A bool found = PED_BE32_TO_CPU (vh->vh_magic) == VHMAGIC;
1N/A free (label);
1N/A return found;
1N/A}
1N/A
1N/Astatic PedDisk*
1N/Advh_alloc (const PedDevice* dev)
1N/A{
1N/A PedDisk* disk;
1N/A DVHDiskData* dvh_disk_data;
1N/A PedPartition* volume_part;
1N/A PedConstraint* constraint_any;
1N/A
1N/A disk = _ped_disk_alloc (dev, &dvh_disk_type);
1N/A if (!disk)
1N/A goto error;
1N/A
1N/A disk->disk_specific = dvh_disk_data
1N/A = ped_malloc (sizeof (DVHDiskData));
1N/A if (!dvh_disk_data)
1N/A goto error_free_disk;
1N/A
1N/A memset (&dvh_disk_data->dev_params, 0,
1N/A sizeof (struct device_parameters));
1N/A dvh_disk_data->swap = 0;
1N/A dvh_disk_data->root = 0;
1N/A dvh_disk_data->boot = 0;
1N/A
1N/A volume_part = ped_partition_new (disk, PED_PARTITION_EXTENDED, NULL,
1N/A 0, PTYPE_VOLHDR_DFLTSZ - 1);
1N/A if (!volume_part)
1N/A goto error_free_disk_specific;
1N/A volume_part->num = PNUM_VOLHDR + 1;
1N/A constraint_any = ped_constraint_any (dev);
1N/A if (!ped_disk_add_partition (disk, volume_part, constraint_any))
1N/A goto error_destroy_constraint_any;
1N/A ped_constraint_destroy (constraint_any);
1N/A return disk;
1N/A
1N/Aerror_destroy_constraint_any:
1N/A ped_constraint_destroy (constraint_any);
1N/A ped_partition_destroy (volume_part);
1N/Aerror_free_disk_specific:
1N/A free (disk->disk_specific);
1N/Aerror_free_disk:
1N/A free (disk);
1N/Aerror:
1N/A return NULL;
1N/A}
1N/A
1N/Astatic PedDisk*
1N/Advh_duplicate (const PedDisk* disk)
1N/A{
1N/A PedDisk* new_disk;
1N/A DVHDiskData* new_dvh_disk_data;
1N/A DVHDiskData* old_dvh_disk_data = disk->disk_specific;
1N/A
1N/A PED_ASSERT (old_dvh_disk_data != NULL, goto error);
1N/A
1N/A new_disk = ped_disk_new_fresh (disk->dev, &dvh_disk_type);
1N/A if (!new_disk)
1N/A goto error;
1N/A
1N/A new_disk->disk_specific = new_dvh_disk_data
1N/A = ped_malloc (sizeof (DVHDiskData));
1N/A if (!new_dvh_disk_data)
1N/A goto error_free_new_disk;
1N/A
1N/A new_dvh_disk_data->dev_params = old_dvh_disk_data->dev_params;
1N/A return new_disk;
1N/A
1N/Aerror_free_new_disk:
1N/A free (new_disk);
1N/Aerror:
1N/A return NULL;
1N/A}
1N/A
1N/Astatic void
1N/Advh_free (PedDisk* disk)
1N/A{
1N/A free (disk->disk_specific);
1N/A _ped_disk_free (disk);
1N/A}
1N/A
1N/A/* two's complement 32-bit checksum */
1N/Astatic uint32_t
1N/A_checksum (const uint32_t* base, size_t size)
1N/A{
1N/A uint32_t sum = 0;
1N/A size_t i;
1N/A
1N/A for (i = 0; i < size / sizeof (uint32_t); i++)
1N/A sum = sum - PED_BE32_TO_CPU (base[i]);
1N/A
1N/A return sum;
1N/A}
1N/A
1N/A/* try to make a reasonable volume header partition... */
1N/Astatic PedExceptionOption
1N/A_handle_no_volume_header (PedDisk* disk)
1N/A{
1N/A PedExceptionOption ret;
1N/A PedPartition* part;
1N/A PedConstraint* constraint;
1N/A
1N/A switch (ped_exception_throw (
1N/A PED_EXCEPTION_WARNING,
1N/A PED_EXCEPTION_FIX + PED_EXCEPTION_CANCEL,
1N/A _("%s has no extended partition (volume header partition)."),
1N/A disk->dev->path)) {
1N/A case PED_EXCEPTION_UNHANDLED:
1N/A case PED_EXCEPTION_FIX:
1N/A default:
1N/A part = ped_partition_new (
1N/A disk, PED_PARTITION_EXTENDED, NULL,
1N/A 0, PTYPE_VOLHDR_DFLTSZ - 1);
1N/A if (!part)
1N/A goto error;
1N/A part->num = PNUM_VOLHDR + 1;
1N/A constraint = ped_constraint_any (part->disk->dev);
1N/A if (!constraint)
1N/A goto error_destroy_part;
1N/A if (!ped_disk_add_partition (disk, part, constraint))
1N/A goto error_destroy_constraint;
1N/A ped_constraint_destroy (constraint);
1N/A ret = PED_EXCEPTION_FIX;
1N/A break;
1N/A
1N/A case PED_EXCEPTION_CANCEL:
1N/A goto error;
1N/A }
1N/A return ret;
1N/A
1N/Aerror_destroy_constraint:
1N/A ped_constraint_destroy (constraint);
1N/Aerror_destroy_part:
1N/A ped_partition_destroy (part);
1N/Aerror:
1N/A return PED_EXCEPTION_CANCEL;
1N/A}
1N/A
1N/Astatic PedPartition*
1N/A_parse_partition (PedDisk* disk, struct partition_table* pt)
1N/A{
1N/A PedPartition* part;
1N/A DVHPartData* dvh_part_data;
1N/A PedSector start = PED_BE32_TO_CPU (pt->pt_firstlbn);
1N/A PedSector length = PED_BE32_TO_CPU (pt->pt_nblks);
1N/A
1N/A part = ped_partition_new (disk,
1N/A pt->pt_type ? 0 : PED_PARTITION_EXTENDED,
1N/A NULL,
1N/A start, start + length - 1);
1N/A if (!part)
1N/A return NULL;
1N/A
1N/A dvh_part_data = part->disk_specific;
1N/A dvh_part_data->type = PED_BE32_TO_CPU (pt->pt_type);
1N/A strcpy (dvh_part_data->name, "");
1N/A
1N/A return part;
1N/A}
1N/A
1N/Astatic PedPartition*
1N/A_parse_boot_file (PedDisk* disk, struct volume_directory* vd)
1N/A{
1N/A PedPartition* part;
1N/A DVHPartData* dvh_part_data;
1N/A PedSector start = PED_BE32_TO_CPU (vd->vd_lbn);
1N/A int length = PED_BE32_TO_CPU (vd->vd_nbytes);
1N/A
1N/A part = ped_partition_new (disk, PED_PARTITION_LOGICAL, NULL,
1N/A start, start + length/512 - 1);
1N/A if (!part)
1N/A return NULL;
1N/A
1N/A dvh_part_data = part->disk_specific;
1N/A dvh_part_data->real_file_size = length;
1N/A
1N/A strncpy (dvh_part_data->name, vd->vd_name, VDNAMESIZE);
1N/A dvh_part_data->name[VDNAMESIZE] = 0;
1N/A return part;
1N/A}
1N/A
1N/Astatic int dvh_write (const PedDisk* disk);
1N/A
1N/A/* YUCK
1N/A *
1N/A * If you remove a boot/root/swap partition, the disk->disk_specific
1N/A * thing isn't updated. (Probably reflects a design bug somewhere...)
1N/A * Anyway, the workaround is: flush stale flags whenever we allocate
1N/A * new partition numbers, and before we write to disk.
1N/A */
1N/Astatic void
1N/A_flush_stale_flags (const PedDisk* disk)
1N/A{
1N/A DVHDiskData* dvh_disk_data = disk->disk_specific;
1N/A
1N/A if (dvh_disk_data->root
1N/A && !ped_disk_get_partition (disk, dvh_disk_data->root))
1N/A dvh_disk_data->root = 0;
1N/A if (dvh_disk_data->swap
1N/A && !ped_disk_get_partition (disk, dvh_disk_data->swap))
1N/A dvh_disk_data->swap = 0;
1N/A if (dvh_disk_data->boot
1N/A && !ped_disk_get_partition (disk, dvh_disk_data->boot))
1N/A dvh_disk_data->boot = 0;
1N/A}
1N/A
1N/Astatic int
1N/Advh_read (PedDisk* disk)
1N/A{
1N/A DVHDiskData* dvh_disk_data = disk->disk_specific;
1N/A int i;
1N/A struct volume_header vh;
1N/A char boot_name [BFNAMESIZE + 1];
1N/A#ifndef DISCOVER_ONLY
1N/A int write_back = 0;
1N/A#endif
1N/A
1N/A PED_ASSERT (dvh_disk_data != NULL, return 0);
1N/A
1N/A ped_disk_delete_all (disk);
1N/A
1N/A char *s0;
1N/A if (!read_sector (disk->dev, 0, &s0))
1N/A return 0;
1N/A memcpy (&vh, s0, sizeof vh);
1N/A free (s0);
1N/A
1N/A if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) {
1N/A if (ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_IGNORE_CANCEL,
1N/A _("Checksum is wrong, indicating the partition "
1N/A "table is corrupt."))
1N/A == PED_EXCEPTION_CANCEL)
1N/A return 0;
1N/A }
1N/A
1N/A PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC, return 0);
1N/A
1N/A dvh_disk_data->dev_params = vh.vh_dp;
1N/A strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE);
1N/A boot_name[BFNAMESIZE] = 0;
1N/A
1N/A /* normal partitions */
1N/A for (i = 0; i < NPARTAB; i++) {
1N/A PedPartition* part;
1N/A
1N/A if (!vh.vh_pt[i].pt_nblks)
1N/A continue;
1N/A /* Skip the whole-disk partition, parted disklikes overlap */
1N/A if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME)
1N/A continue;
1N/A
1N/A part = _parse_partition (disk, &vh.vh_pt[i]);
1N/A if (!part)
1N/A goto error_delete_all;
1N/A
1N/A part->fs_type = ped_file_system_probe (&part->geom);
1N/A part->num = i + 1;
1N/A
1N/A if (PED_BE16_TO_CPU (vh.vh_rootpt) == i)
1N/A ped_partition_set_flag (part, PED_PARTITION_ROOT, 1);
1N/A if (PED_BE16_TO_CPU (vh.vh_swappt) == i)
1N/A ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1N/A
1N/A PedConstraint *constraint_exact
1N/A = ped_constraint_exact (&part->geom);
1N/A bool ok = ped_disk_add_partition (disk, part, constraint_exact);
1N/A ped_constraint_destroy (constraint_exact);
1N/A if (!ok) {
1N/A ped_partition_destroy (part);
1N/A goto error_delete_all;
1N/A }
1N/A }
1N/A
1N/A if (!ped_disk_extended_partition (disk)) {
1N/A#ifdef DISCOVER_ONLY
1N/A return 1;
1N/A#else
1N/A switch (_handle_no_volume_header (disk)) {
1N/A case PED_EXCEPTION_CANCEL:
1N/A return 0;
1N/A case PED_EXCEPTION_IGNORE:
1N/A return 1;
1N/A case PED_EXCEPTION_FIX:
1N/A write_back = 1;
1N/A break;
1N/A default:
1N/A break;
1N/A }
1N/A#endif
1N/A }
1N/A
1N/A /* boot partitions */
1N/A for (i = 0; i < NVDIR; i++) {
1N/A PedPartition* part;
1N/A
1N/A if (!vh.vh_vd[i].vd_nbytes)
1N/A continue;
1N/A
1N/A part = _parse_boot_file (disk, &vh.vh_vd[i]);
1N/A if (!part)
1N/A goto error_delete_all;
1N/A
1N/A part->fs_type = ped_file_system_probe (&part->geom);
1N/A part->num = NPARTAB + i + 1;
1N/A
1N/A if (!strcmp (boot_name, ped_partition_get_name (part)))
1N/A ped_partition_set_flag (part, PED_PARTITION_BOOT, 1);
1N/A
1N/A PedConstraint *constraint_exact
1N/A = ped_constraint_exact (&part->geom);
1N/A bool ok = ped_disk_add_partition (disk, part, constraint_exact);
1N/A ped_constraint_destroy (constraint_exact);
1N/A if (!ok) {
1N/A ped_partition_destroy (part);
1N/A goto error_delete_all;
1N/A }
1N/A }
1N/A#ifndef DISCOVER_ONLY
1N/A if (write_back)
1N/A dvh_write (disk);
1N/A#endif
1N/A return 1;
1N/A
1N/Aerror_delete_all:
1N/A ped_disk_delete_all (disk);
1N/A return 0;
1N/A}
1N/A
1N/A#ifndef DISCOVER_ONLY
1N/Astatic void
1N/A_generate_partition (PedPartition* part, struct partition_table* pt)
1N/A{
1N/A DVHPartData* dvh_part_data = part->disk_specific;
1N/A
1N/A /* Assert not a bootfile */
1N/A PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) == 0, return);
1N/A
1N/A pt->pt_nblks = PED_CPU_TO_BE32 (part->geom.length);
1N/A pt->pt_firstlbn = PED_CPU_TO_BE32 (part->geom.start);
1N/A pt->pt_type = PED_CPU_TO_BE32 (dvh_part_data->type);
1N/A}
1N/A
1N/Astatic void
1N/A_generate_boot_file (PedPartition* part, struct volume_directory* vd)
1N/A{
1N/A DVHPartData* dvh_part_data = part->disk_specific;
1N/A
1N/A /* Assert it's a bootfile */
1N/A PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) != 0, return);
1N/A
1N/A vd->vd_nbytes = PED_CPU_TO_BE32 (dvh_part_data->real_file_size);
1N/A vd->vd_lbn = PED_CPU_TO_BE32 (part->geom.start);
1N/A
1N/A memset (vd->vd_name, 0, VDNAMESIZE);
1N/A strncpy (vd->vd_name, dvh_part_data->name, VDNAMESIZE);
1N/A}
1N/A
1N/Astatic int
1N/Advh_write (const PedDisk* disk)
1N/A{
1N/A DVHDiskData* dvh_disk_data = disk->disk_specific;
1N/A struct volume_header vh;
1N/A int i;
1N/A
1N/A PED_ASSERT (dvh_disk_data != NULL, return 0);
1N/A
1N/A _flush_stale_flags (disk);
1N/A
1N/A memset (&vh, 0, sizeof (struct volume_header));
1N/A
1N/A vh.vh_magic = PED_CPU_TO_BE32 (VHMAGIC);
1N/A vh.vh_rootpt = PED_CPU_TO_BE16 (dvh_disk_data->root - 1);
1N/A vh.vh_swappt = PED_CPU_TO_BE16 (dvh_disk_data->swap - 1);
1N/A
1N/A if (dvh_disk_data->boot) {
1N/A PedPartition* boot_part;
1N/A boot_part = ped_disk_get_partition (disk, dvh_disk_data->boot);
1N/A strcpy (vh.vh_bootfile, ped_partition_get_name (boot_part));
1N/A }
1N/A
1N/A vh.vh_dp = dvh_disk_data->dev_params;
1N/A /* Set up rudimentary device geometry */
1N/A vh.vh_dp.dp_cyls
1N/A = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.cylinders);
1N/A vh.vh_dp.dp_trks0 = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.heads);
1N/A vh.vh_dp.dp_secs
1N/A = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.sectors);
1N/A vh.vh_dp.dp_secbytes = PED_CPU_TO_BE16 ((short)disk->dev->sector_size);
1N/A
1N/A for (i = 0; i < NPARTAB; i++) {
1N/A PedPartition* part = ped_disk_get_partition (disk, i + 1);
1N/A if (part)
1N/A _generate_partition (part, &vh.vh_pt[i]);
1N/A }
1N/A
1N/A /* whole disk partition
1N/A * This is only ever written here, and never modified
1N/A * (or even shown) as it must contain the entire disk,
1N/A * and parted does not like overlapping partitions
1N/A */
1N/A vh.vh_pt[PNUM_VOLUME].pt_nblks = PED_CPU_TO_BE32 (disk->dev->length);
1N/A vh.vh_pt[PNUM_VOLUME].pt_firstlbn = PED_CPU_TO_BE32 (0);
1N/A vh.vh_pt[PNUM_VOLUME].pt_type = PED_CPU_TO_BE32 (PTYPE_VOLUME);
1N/A
1N/A for (i = 0; i < NVDIR; i++) {
1N/A PedPartition* part = ped_disk_get_partition (disk,
1N/A i + 1 + NPARTAB);
1N/A if (part)
1N/A _generate_boot_file (part, &vh.vh_vd[i]);
1N/A }
1N/A
1N/A vh.vh_csum = 0;
1N/A vh.vh_csum = PED_CPU_TO_BE32 (_checksum ((uint32_t*) &vh,
1N/A sizeof (struct volume_header)));
1N/A
1N/A return (ptt_write_sector (disk, &vh, sizeof vh)
1N/A && ped_device_sync (disk->dev));
1N/A}
1N/A#endif /* !DISCOVER_ONLY */
1N/A
1N/Astatic PedPartition*
1N/Advh_partition_new (const PedDisk* disk, PedPartitionType part_type,
1N/A const PedFileSystemType* fs_type,
1N/A PedSector start, PedSector end)
1N/A{
1N/A PedPartition* part;
1N/A DVHPartData* dvh_part_data;
1N/A
1N/A part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1N/A if (!part)
1N/A goto error;
1N/A
1N/A if (!ped_partition_is_active (part)) {
1N/A part->disk_specific = NULL;
1N/A return part;
1N/A }
1N/A
1N/A dvh_part_data = part->disk_specific =
1N/A ped_malloc (sizeof (DVHPartData));
1N/A if (!dvh_part_data)
1N/A goto error_free_part;
1N/A
1N/A dvh_part_data->type = (part_type == PED_PARTITION_EXTENDED)
1N/A ? PTYPE_VOLHDR
1N/A : PTYPE_RAW;
1N/A strcpy (dvh_part_data->name, "");
1N/A dvh_part_data->real_file_size = part->geom.length * 512;
1N/A return part;
1N/A
1N/Aerror_free_part:
1N/A _ped_partition_free (part);
1N/Aerror:
1N/A return NULL;
1N/A}
1N/A
1N/Astatic PedPartition*
1N/Advh_partition_duplicate (const PedPartition* part)
1N/A{
1N/A PedPartition* result;
1N/A DVHPartData* part_data = part->disk_specific;
1N/A DVHPartData* result_data;
1N/A
1N/A result = _ped_partition_alloc (part->disk, part->type, part->fs_type,
1N/A part->geom.start, part->geom.end);
1N/A if (!result)
1N/A goto error;
1N/A result->num = part->num;
1N/A
1N/A if (!ped_partition_is_active (part)) {
1N/A result->disk_specific = NULL;
1N/A return result;
1N/A }
1N/A
1N/A result_data = result->disk_specific =
1N/A ped_malloc (sizeof (DVHPartData));
1N/A if (!result_data)
1N/A goto error_free_part;
1N/A
1N/A result_data->type = part_data->type;
1N/A strcpy (result_data->name, part_data->name);
1N/A result_data->real_file_size = part_data->real_file_size;
1N/A return result;
1N/A
1N/Aerror_free_part:
1N/A _ped_partition_free (result);
1N/Aerror:
1N/A return NULL;
1N/A}
1N/A
1N/Astatic void
1N/Advh_partition_destroy (PedPartition* part)
1N/A{
1N/A if (ped_partition_is_active (part)) {
1N/A PED_ASSERT (part->disk_specific != NULL, return);
1N/A free (part->disk_specific);
1N/A }
1N/A _ped_partition_free (part);
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1N/A{
1N/A DVHPartData* dvh_part_data = part->disk_specific;
1N/A
1N/A part->fs_type = fs_type;
1N/A
1N/A if (part->type == PED_PARTITION_EXTENDED) {
1N/A dvh_part_data->type = PTYPE_VOLHDR;
1N/A return 1;
1N/A }
1N/A
1N/A /* Is this a bootfile? */
1N/A if (part->type == PED_PARTITION_LOGICAL)
1N/A return 1;
1N/A
1N/A if (fs_type && !strcmp (fs_type->name, "xfs"))
1N/A dvh_part_data->type = PTYPE_XFS;
1N/A else
1N/A dvh_part_data->type = PTYPE_RAW;
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1N/A{
1N/A DVHDiskData* dvh_disk_data = part->disk->disk_specific;
1N/A
1N/A switch (flag) {
1N/A case PED_PARTITION_ROOT:
1N/A if (part->type != 0 && state) {
1N/A#ifndef DISCOVER_ONLY
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Only primary partitions can be root "
1N/A "partitions."));
1N/A#endif
1N/A return 0;
1N/A }
1N/A dvh_disk_data->root = state ? part->num : 0;
1N/A break;
1N/A
1N/A case PED_PARTITION_SWAP:
1N/A if (part->type != 0 && state) {
1N/A#ifndef DISCOVER_ONLY
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Only primary partitions can be swap "
1N/A "partitions."));
1N/A return 0;
1N/A#endif
1N/A }
1N/A dvh_disk_data->swap = state ? part->num : 0;
1N/A break;
1N/A
1N/A case PED_PARTITION_BOOT:
1N/A if (part->type != PED_PARTITION_LOGICAL && state) {
1N/A#ifndef DISCOVER_ONLY
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Only logical partitions can be a boot "
1N/A "file."));
1N/A#endif
1N/A return 0;
1N/A }
1N/A dvh_disk_data->boot = state ? part->num : 0;
1N/A break;
1N/A
1N/A case PED_PARTITION_LVM:
1N/A case PED_PARTITION_LBA:
1N/A case PED_PARTITION_HIDDEN:
1N/A case PED_PARTITION_RAID:
1N/A default:
1N/A return 0;
1N/A }
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1N/A{
1N/A DVHDiskData* dvh_disk_data = part->disk->disk_specific;
1N/A
1N/A switch (flag) {
1N/A case PED_PARTITION_ROOT:
1N/A return dvh_disk_data->root == part->num;
1N/A
1N/A case PED_PARTITION_SWAP:
1N/A return dvh_disk_data->swap == part->num;
1N/A
1N/A case PED_PARTITION_BOOT:
1N/A return dvh_disk_data->boot == part->num;
1N/A
1N/A case PED_PARTITION_LVM:
1N/A case PED_PARTITION_LBA:
1N/A case PED_PARTITION_HIDDEN:
1N/A case PED_PARTITION_RAID:
1N/A default:
1N/A return 0;
1N/A }
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_is_flag_available (const PedPartition* part,
1N/A PedPartitionFlag flag)
1N/A{
1N/A switch (flag) {
1N/A case PED_PARTITION_ROOT:
1N/A case PED_PARTITION_SWAP:
1N/A case PED_PARTITION_BOOT:
1N/A return 1;
1N/A
1N/A case PED_PARTITION_LVM:
1N/A case PED_PARTITION_LBA:
1N/A case PED_PARTITION_HIDDEN:
1N/A case PED_PARTITION_RAID:
1N/A default:
1N/A return 0;
1N/A }
1N/A return 1;
1N/A}
1N/A
1N/Astatic void
1N/Advh_partition_set_name (PedPartition* part, const char* name)
1N/A{
1N/A DVHPartData* dvh_part_data = part->disk_specific;
1N/A
1N/A if (part->type == PED_PARTITION_LOGICAL) {
1N/A /* Bootfile */
1N/A strncpy (dvh_part_data->name, name, VDNAMESIZE);
1N/A dvh_part_data->name[VDNAMESIZE] = 0;
1N/A } else {
1N/A#ifndef DISCOVER_ONLY
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("failed to set dvh partition name to %s:\n"
1N/A "Only logical partitions (boot files) have a name."),
1N/A name);
1N/A#endif
1N/A }
1N/A}
1N/A
1N/Astatic const char*
1N/Advh_partition_get_name (const PedPartition* part)
1N/A{
1N/A DVHPartData* dvh_part_data = part->disk_specific;
1N/A return dvh_part_data->name;
1N/A}
1N/A
1N/A/* The constraint for the volume header partition is different, because it must
1N/A * contain the first sector of the disk.
1N/A */
1N/Astatic PedConstraint*
1N/A_get_extended_constraint (PedDisk* disk)
1N/A{
1N/A PedGeometry min_geom;
1N/A if (!ped_geometry_init (&min_geom, disk->dev, 0, 1))
1N/A return NULL;
1N/A return ped_constraint_new_from_min (&min_geom);
1N/A}
1N/A
1N/Astatic PedConstraint*
1N/A_get_primary_constraint (PedDisk* disk)
1N/A{
1N/A PedGeometry max_geom;
1N/A if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1N/A return NULL;
1N/A return ped_constraint_new_from_max (&max_geom);
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_align (PedPartition* part, const PedConstraint* constraint)
1N/A{
1N/A PED_ASSERT (part != NULL, return 0);
1N/A
1N/A if (_ped_partition_attempt_align (
1N/A part, constraint,
1N/A (part->type == PED_PARTITION_EXTENDED)
1N/A ? _get_extended_constraint (part->disk)
1N/A : _get_primary_constraint (part->disk)))
1N/A return 1;
1N/A
1N/A#ifndef DISCOVER_ONLY
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Unable to satisfy all constraints on the partition."));
1N/A#endif
1N/A return 0;
1N/A}
1N/A
1N/Astatic int
1N/Advh_partition_enumerate (PedPartition* part)
1N/A{
1N/A int i;
1N/A
1N/A /* never change the partition numbers */
1N/A if (part->num != -1)
1N/A return 1;
1N/A
1N/A _flush_stale_flags (part->disk);
1N/A
1N/A if (part->type & PED_PARTITION_LOGICAL) {
1N/A /* Bootfile */
1N/A for (i = 1 + NPARTAB; i <= NPARTAB + NVDIR; i++) {
1N/A if (!ped_disk_get_partition (part->disk, i)) {
1N/A part->num = i;
1N/A return 1;
1N/A }
1N/A }
1N/A PED_ASSERT (0, return 0);
1N/A } else if (part->type & PED_PARTITION_EXTENDED) {
1N/A /* Volheader */
1N/A part->num = PNUM_VOLHDR + 1;
1N/A } else {
1N/A for (i = 1; i <= NPARTAB; i++) {
1N/A /* reserved for full volume partition */
1N/A if (i == PNUM_VOLUME + 1)
1N/A continue;
1N/A
1N/A if (!ped_disk_get_partition (part->disk, i)) {
1N/A part->num = i;
1N/A return 1;
1N/A }
1N/A }
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Too many primary partitions"));
1N/A }
1N/A
1N/A return 0;
1N/A}
1N/A
1N/Astatic int
1N/Advh_get_max_primary_partition_count (const PedDisk* disk)
1N/A{
1N/A return NPARTAB;
1N/A}
1N/A
1N/Astatic bool
1N/Advh_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1N/A{
1N/A *max_n = NPARTAB;
1N/A return true;
1N/A}
1N/A
1N/A
1N/Astatic int
1N/Advh_alloc_metadata (PedDisk* disk)
1N/A{
1N/A PedPartition* part;
1N/A PedPartition* extended_part;
1N/A PedPartitionType metadata_type;
1N/A PED_ASSERT(disk != NULL, return 0);
1N/A
1N/A /* We don't need to "protect" the start of the disk from the volume
1N/A * header.
1N/A */
1N/A extended_part = ped_disk_extended_partition (disk);
1N/A if (extended_part && extended_part->geom.start == 0)
1N/A metadata_type = PED_PARTITION_METADATA | PED_PARTITION_LOGICAL;
1N/A else
1N/A metadata_type = PED_PARTITION_METADATA;
1N/A
1N/A part = ped_partition_new (disk, metadata_type, NULL, 0, 0);
1N/A if (!part)
1N/A goto error;
1N/A
1N/A PedConstraint *constraint_exact
1N/A = ped_constraint_exact (&part->geom);
1N/A bool ok = ped_disk_add_partition (disk, part, constraint_exact);
1N/A ped_constraint_destroy (constraint_exact);
1N/A if (ok)
1N/A return 1;
1N/A
1N/A ped_partition_destroy (part);
1N/Aerror:
1N/A return 0;
1N/A}
1N/A
1N/A#include "pt-common.h"
1N/APT_define_limit_functions (dvh)
1N/A
1N/Astatic PedDiskOps dvh_disk_ops = {
1N/A .clobber = NULL,
1N/A .write = NULL_IF_DISCOVER_ONLY (dvh_write),
1N/A
1N/A .partition_set_name = dvh_partition_set_name,
1N/A .partition_get_name = dvh_partition_get_name,
1N/A PT_op_function_initializers (dvh)
1N/A};
1N/A
1N/Astatic PedDiskType dvh_disk_type = {
1N/A .next = NULL,
1N/A .name = "dvh",
1N/A .ops = &dvh_disk_ops,
1N/A .features = PED_DISK_TYPE_PARTITION_NAME | PED_DISK_TYPE_EXTENDED
1N/A};
1N/A
1N/Avoid
1N/Aped_disk_dvh_init ()
1N/A{
1N/A PED_ASSERT (sizeof (struct volume_header) == 512, return);
1N/A
1N/A ped_disk_type_register (&dvh_disk_type);
1N/A}
1N/A
1N/Avoid
1N/Aped_disk_dvh_done ()
1N/A{
1N/A ped_disk_type_unregister (&dvh_disk_type);
1N/A}