pmt: initial 3.0.2 update
This commit is contained in:
896
jni/parted/libparted/labels/dvh.c
Executable file
896
jni/parted/libparted/labels/dvh.c
Executable file
@@ -0,0 +1,896 @@
|
||||
/*
|
||||
libparted - a library for manipulating disk partitions
|
||||
Copyright (C) 2001-2002, 2005, 2007-2014, 2019-2023 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <parted/parted.h>
|
||||
#include <parted/debug.h>
|
||||
#include <parted/endian.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dvh.h"
|
||||
#include "pt-tools.h"
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(String) dgettext (PACKAGE, String)
|
||||
#else
|
||||
# define _(String) (String)
|
||||
#endif /* ENABLE_NLS */
|
||||
|
||||
/* Default size for volhdr part, same val as IRIX's fx uses */
|
||||
#define PTYPE_VOLHDR_DFLTSZ 4096
|
||||
|
||||
/* Partition numbers that seem to be strongly held convention */
|
||||
#define PNUM_VOLHDR 8
|
||||
#define PNUM_VOLUME 10
|
||||
|
||||
/* Other notes of interest:
|
||||
* PED_PARTITION_EXTENDED is used for volume headers
|
||||
* PED_PARTITION_LOGICAL is used for bootfiles
|
||||
* PED_PARTITION_NORMAL is used for all else
|
||||
*/
|
||||
|
||||
typedef struct _DVHDiskData {
|
||||
struct device_parameters dev_params;
|
||||
int swap; /* part num of swap, 0=none */
|
||||
int root; /* part num of root, 0=none */
|
||||
int boot; /* part num of boot, 0=none */
|
||||
} DVHDiskData;
|
||||
|
||||
typedef struct _DVHPartData {
|
||||
int type;
|
||||
char name[VDNAMESIZE + 1]; /* boot volumes only */
|
||||
int real_file_size; /* boot volumes only */
|
||||
} DVHPartData;
|
||||
|
||||
static PedDiskType dvh_disk_type;
|
||||
|
||||
static int
|
||||
dvh_probe (const PedDevice *dev)
|
||||
{
|
||||
struct volume_header *vh;
|
||||
|
||||
void *label;
|
||||
if (!ptt_read_sector (dev, 0, &label))
|
||||
return 0;
|
||||
|
||||
vh = (struct volume_header *) label;
|
||||
|
||||
bool found = PED_BE32_TO_CPU (vh->vh_magic) == VHMAGIC;
|
||||
free (label);
|
||||
return found;
|
||||
}
|
||||
|
||||
static PedDisk*
|
||||
dvh_alloc (const PedDevice* dev)
|
||||
{
|
||||
PedDisk* disk;
|
||||
DVHDiskData* dvh_disk_data;
|
||||
PedPartition* volume_part;
|
||||
PedConstraint* constraint_any;
|
||||
|
||||
disk = _ped_disk_alloc (dev, &dvh_disk_type);
|
||||
if (!disk)
|
||||
goto error;
|
||||
|
||||
disk->disk_specific = dvh_disk_data
|
||||
= ped_malloc (sizeof (DVHDiskData));
|
||||
if (!dvh_disk_data)
|
||||
goto error_free_disk;
|
||||
|
||||
memset (&dvh_disk_data->dev_params, 0,
|
||||
sizeof (struct device_parameters));
|
||||
dvh_disk_data->swap = 0;
|
||||
dvh_disk_data->root = 0;
|
||||
dvh_disk_data->boot = 0;
|
||||
|
||||
volume_part = ped_partition_new (disk, PED_PARTITION_EXTENDED, NULL,
|
||||
0, PTYPE_VOLHDR_DFLTSZ - 1);
|
||||
if (!volume_part)
|
||||
goto error_free_disk_specific;
|
||||
volume_part->num = PNUM_VOLHDR + 1;
|
||||
constraint_any = ped_constraint_any (dev);
|
||||
if (!ped_disk_add_partition (disk, volume_part, constraint_any))
|
||||
goto error_destroy_constraint_any;
|
||||
ped_constraint_destroy (constraint_any);
|
||||
return disk;
|
||||
|
||||
error_destroy_constraint_any:
|
||||
ped_constraint_destroy (constraint_any);
|
||||
ped_partition_destroy (volume_part);
|
||||
error_free_disk_specific:
|
||||
free (disk->disk_specific);
|
||||
error_free_disk:
|
||||
free (disk);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PedDisk*
|
||||
dvh_duplicate (const PedDisk* disk)
|
||||
{
|
||||
PedDisk* new_disk;
|
||||
DVHDiskData* new_dvh_disk_data;
|
||||
DVHDiskData* old_dvh_disk_data = disk->disk_specific;
|
||||
|
||||
PED_ASSERT (old_dvh_disk_data != NULL);
|
||||
|
||||
new_disk = ped_disk_new_fresh (disk->dev, &dvh_disk_type);
|
||||
if (!new_disk)
|
||||
goto error;
|
||||
|
||||
new_disk->disk_specific = new_dvh_disk_data
|
||||
= ped_malloc (sizeof (DVHDiskData));
|
||||
if (!new_dvh_disk_data)
|
||||
goto error_free_new_disk;
|
||||
|
||||
new_dvh_disk_data->dev_params = old_dvh_disk_data->dev_params;
|
||||
return new_disk;
|
||||
|
||||
error_free_new_disk:
|
||||
free (new_disk);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dvh_free (PedDisk* disk)
|
||||
{
|
||||
free (disk->disk_specific);
|
||||
_ped_disk_free (disk);
|
||||
}
|
||||
|
||||
/* two's complement 32-bit checksum */
|
||||
static uint32_t _GL_ATTRIBUTE_PURE
|
||||
_checksum (const uint32_t* base, size_t size)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size / sizeof (uint32_t); i++)
|
||||
sum = sum - PED_BE32_TO_CPU (base[i]);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* try to make a reasonable volume header partition... */
|
||||
static PedExceptionOption
|
||||
_handle_no_volume_header (PedDisk* disk)
|
||||
{
|
||||
PedExceptionOption ret;
|
||||
PedPartition* part;
|
||||
PedConstraint* constraint;
|
||||
|
||||
switch (ped_exception_throw (
|
||||
PED_EXCEPTION_WARNING,
|
||||
PED_EXCEPTION_FIX + PED_EXCEPTION_CANCEL,
|
||||
_("%s has no extended partition (volume header partition)."),
|
||||
disk->dev->path)) {
|
||||
case PED_EXCEPTION_UNHANDLED:
|
||||
case PED_EXCEPTION_FIX:
|
||||
default:
|
||||
part = ped_partition_new (
|
||||
disk, PED_PARTITION_EXTENDED, NULL,
|
||||
0, PTYPE_VOLHDR_DFLTSZ - 1);
|
||||
if (!part)
|
||||
goto error;
|
||||
part->num = PNUM_VOLHDR + 1;
|
||||
constraint = ped_constraint_any (part->disk->dev);
|
||||
if (!constraint)
|
||||
goto error_destroy_part;
|
||||
if (!ped_disk_add_partition (disk, part, constraint))
|
||||
goto error_destroy_constraint;
|
||||
ped_constraint_destroy (constraint);
|
||||
ret = PED_EXCEPTION_FIX;
|
||||
break;
|
||||
|
||||
case PED_EXCEPTION_CANCEL:
|
||||
goto error;
|
||||
}
|
||||
return ret;
|
||||
|
||||
error_destroy_constraint:
|
||||
ped_constraint_destroy (constraint);
|
||||
error_destroy_part:
|
||||
ped_partition_destroy (part);
|
||||
error:
|
||||
return PED_EXCEPTION_CANCEL;
|
||||
}
|
||||
|
||||
static PedPartition*
|
||||
_parse_partition (PedDisk* disk, struct partition_table* pt)
|
||||
{
|
||||
PedPartition* part;
|
||||
DVHPartData* dvh_part_data;
|
||||
PedSector start = PED_BE32_TO_CPU (pt->pt_firstlbn);
|
||||
PedSector length = PED_BE32_TO_CPU (pt->pt_nblks);
|
||||
|
||||
part = ped_partition_new (disk,
|
||||
pt->pt_type ? 0 : PED_PARTITION_EXTENDED,
|
||||
NULL,
|
||||
start, start + length - 1);
|
||||
if (!part)
|
||||
return NULL;
|
||||
|
||||
dvh_part_data = part->disk_specific;
|
||||
dvh_part_data->type = PED_BE32_TO_CPU (pt->pt_type);
|
||||
strcpy (dvh_part_data->name, "");
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
static PedPartition*
|
||||
_parse_boot_file (PedDisk* disk, struct volume_directory* vd)
|
||||
{
|
||||
PedPartition* part;
|
||||
DVHPartData* dvh_part_data;
|
||||
PedSector start = PED_BE32_TO_CPU (vd->vd_lbn);
|
||||
int length = PED_BE32_TO_CPU (vd->vd_nbytes);
|
||||
|
||||
part = ped_partition_new (disk, PED_PARTITION_LOGICAL, NULL,
|
||||
start, start + length/512 - 1);
|
||||
if (!part)
|
||||
return NULL;
|
||||
|
||||
dvh_part_data = part->disk_specific;
|
||||
dvh_part_data->real_file_size = length;
|
||||
|
||||
memcpy (dvh_part_data->name, vd->vd_name, VDNAMESIZE);
|
||||
dvh_part_data->name[VDNAMESIZE] = 0;
|
||||
return part;
|
||||
}
|
||||
|
||||
static int dvh_write (const PedDisk* disk);
|
||||
|
||||
/* YUCK
|
||||
*
|
||||
* If you remove a boot/root/swap partition, the disk->disk_specific
|
||||
* thing isn't updated. (Probably reflects a design bug somewhere...)
|
||||
* Anyway, the workaround is: flush stale flags whenever we allocate
|
||||
* new partition numbers, and before we write to disk.
|
||||
*/
|
||||
static void
|
||||
_flush_stale_flags (const PedDisk* disk)
|
||||
{
|
||||
DVHDiskData* dvh_disk_data = disk->disk_specific;
|
||||
|
||||
if (dvh_disk_data->root
|
||||
&& !ped_disk_get_partition (disk, dvh_disk_data->root))
|
||||
dvh_disk_data->root = 0;
|
||||
if (dvh_disk_data->swap
|
||||
&& !ped_disk_get_partition (disk, dvh_disk_data->swap))
|
||||
dvh_disk_data->swap = 0;
|
||||
if (dvh_disk_data->boot
|
||||
&& !ped_disk_get_partition (disk, dvh_disk_data->boot))
|
||||
dvh_disk_data->boot = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_read (PedDisk* disk)
|
||||
{
|
||||
DVHDiskData* dvh_disk_data = disk->disk_specific;
|
||||
int i;
|
||||
struct volume_header vh;
|
||||
char boot_name [BFNAMESIZE + 1];
|
||||
#ifndef DISCOVER_ONLY
|
||||
int write_back = 0;
|
||||
#endif
|
||||
|
||||
PED_ASSERT (dvh_disk_data != NULL);
|
||||
|
||||
ped_disk_delete_all (disk);
|
||||
|
||||
void *s0;
|
||||
if (!ptt_read_sector (disk->dev, 0, &s0))
|
||||
return 0;
|
||||
memcpy (&vh, s0, sizeof vh);
|
||||
free (s0);
|
||||
|
||||
if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) {
|
||||
if (ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_IGNORE_CANCEL,
|
||||
_("Checksum is wrong, indicating the partition "
|
||||
"table is corrupt."))
|
||||
== PED_EXCEPTION_CANCEL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC);
|
||||
|
||||
dvh_disk_data->dev_params = vh.vh_dp;
|
||||
boot_name[BFNAMESIZE] = 0;
|
||||
strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE);
|
||||
|
||||
/* normal partitions */
|
||||
for (i = 0; i < NPARTAB; i++) {
|
||||
PedPartition* part;
|
||||
|
||||
if (!vh.vh_pt[i].pt_nblks)
|
||||
continue;
|
||||
/* Skip the whole-disk partition, parted disklikes overlap */
|
||||
if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME)
|
||||
continue;
|
||||
|
||||
part = _parse_partition (disk, &vh.vh_pt[i]);
|
||||
if (!part)
|
||||
goto error_delete_all;
|
||||
|
||||
part->fs_type = ped_file_system_probe (&part->geom);
|
||||
part->num = i + 1;
|
||||
|
||||
if (PED_BE16_TO_CPU (vh.vh_rootpt) == i)
|
||||
ped_partition_set_flag (part, PED_PARTITION_ROOT, 1);
|
||||
if (PED_BE16_TO_CPU (vh.vh_swappt) == i)
|
||||
ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
|
||||
|
||||
PedConstraint *constraint_exact
|
||||
= ped_constraint_exact (&part->geom);
|
||||
bool ok = ped_disk_add_partition (disk, part, constraint_exact);
|
||||
ped_constraint_destroy (constraint_exact);
|
||||
if (!ok) {
|
||||
ped_partition_destroy (part);
|
||||
goto error_delete_all;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ped_disk_extended_partition (disk)) {
|
||||
#ifdef DISCOVER_ONLY
|
||||
return 1;
|
||||
#else
|
||||
switch (_handle_no_volume_header (disk)) {
|
||||
case PED_EXCEPTION_CANCEL:
|
||||
return 0;
|
||||
case PED_EXCEPTION_IGNORE:
|
||||
return 1;
|
||||
case PED_EXCEPTION_FIX:
|
||||
write_back = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* boot partitions */
|
||||
for (i = 0; i < NVDIR; i++) {
|
||||
PedPartition* part;
|
||||
|
||||
if (!vh.vh_vd[i].vd_nbytes)
|
||||
continue;
|
||||
|
||||
part = _parse_boot_file (disk, &vh.vh_vd[i]);
|
||||
if (!part)
|
||||
goto error_delete_all;
|
||||
|
||||
part->fs_type = ped_file_system_probe (&part->geom);
|
||||
part->num = NPARTAB + i + 1;
|
||||
|
||||
if (!strcmp (boot_name, ped_partition_get_name (part)))
|
||||
ped_partition_set_flag (part, PED_PARTITION_BOOT, 1);
|
||||
|
||||
PedConstraint *constraint_exact
|
||||
= ped_constraint_exact (&part->geom);
|
||||
bool ok = ped_disk_add_partition (disk, part, constraint_exact);
|
||||
ped_constraint_destroy (constraint_exact);
|
||||
if (!ok) {
|
||||
ped_partition_destroy (part);
|
||||
goto error_delete_all;
|
||||
}
|
||||
}
|
||||
#ifndef DISCOVER_ONLY
|
||||
if (write_back)
|
||||
dvh_write (disk);
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
error_delete_all:
|
||||
ped_disk_delete_all (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DISCOVER_ONLY
|
||||
static void
|
||||
_generate_partition (PedPartition* part, struct partition_table* pt)
|
||||
{
|
||||
DVHPartData* dvh_part_data = part->disk_specific;
|
||||
|
||||
/* Assert not a bootfile */
|
||||
PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) == 0);
|
||||
|
||||
pt->pt_nblks = PED_CPU_TO_BE32 (part->geom.length);
|
||||
pt->pt_firstlbn = PED_CPU_TO_BE32 (part->geom.start);
|
||||
pt->pt_type = PED_CPU_TO_BE32 (dvh_part_data->type);
|
||||
}
|
||||
|
||||
static void
|
||||
_generate_boot_file (PedPartition* part, struct volume_directory* vd)
|
||||
{
|
||||
DVHPartData* dvh_part_data = part->disk_specific;
|
||||
|
||||
/* Assert it's a bootfile */
|
||||
PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) != 0);
|
||||
|
||||
vd->vd_nbytes = PED_CPU_TO_BE32 (dvh_part_data->real_file_size);
|
||||
vd->vd_lbn = PED_CPU_TO_BE32 (part->geom.start);
|
||||
|
||||
memset (vd->vd_name, 0, VDNAMESIZE);
|
||||
memcpy (vd->vd_name, dvh_part_data->name, VDNAMESIZE);
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_write (const PedDisk* disk)
|
||||
{
|
||||
DVHDiskData* dvh_disk_data = disk->disk_specific;
|
||||
struct volume_header vh;
|
||||
int i;
|
||||
|
||||
PED_ASSERT (dvh_disk_data != NULL);
|
||||
|
||||
_flush_stale_flags (disk);
|
||||
|
||||
memset (&vh, 0, sizeof (struct volume_header));
|
||||
|
||||
vh.vh_magic = PED_CPU_TO_BE32 (VHMAGIC);
|
||||
vh.vh_rootpt = PED_CPU_TO_BE16 (dvh_disk_data->root - 1);
|
||||
vh.vh_swappt = PED_CPU_TO_BE16 (dvh_disk_data->swap - 1);
|
||||
|
||||
if (dvh_disk_data->boot) {
|
||||
PedPartition* boot_part;
|
||||
boot_part = ped_disk_get_partition (disk, dvh_disk_data->boot);
|
||||
strcpy (vh.vh_bootfile, ped_partition_get_name (boot_part));
|
||||
}
|
||||
|
||||
vh.vh_dp = dvh_disk_data->dev_params;
|
||||
/* Set up rudimentary device geometry */
|
||||
vh.vh_dp.dp_cyls
|
||||
= PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.cylinders);
|
||||
vh.vh_dp.dp_trks0 = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.heads);
|
||||
vh.vh_dp.dp_secs
|
||||
= PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.sectors);
|
||||
vh.vh_dp.dp_secbytes = PED_CPU_TO_BE16 ((short)disk->dev->sector_size);
|
||||
|
||||
for (i = 0; i < NPARTAB; i++) {
|
||||
PedPartition* part = ped_disk_get_partition (disk, i + 1);
|
||||
if (part)
|
||||
_generate_partition (part, &vh.vh_pt[i]);
|
||||
}
|
||||
|
||||
/* whole disk partition
|
||||
* This is only ever written here, and never modified
|
||||
* (or even shown) as it must contain the entire disk,
|
||||
* and parted does not like overlapping partitions
|
||||
*/
|
||||
vh.vh_pt[PNUM_VOLUME].pt_nblks = PED_CPU_TO_BE32 (disk->dev->length);
|
||||
vh.vh_pt[PNUM_VOLUME].pt_firstlbn = PED_CPU_TO_BE32 (0);
|
||||
vh.vh_pt[PNUM_VOLUME].pt_type = PED_CPU_TO_BE32 (PTYPE_VOLUME);
|
||||
|
||||
for (i = 0; i < NVDIR; i++) {
|
||||
PedPartition* part = ped_disk_get_partition (disk,
|
||||
i + 1 + NPARTAB);
|
||||
if (part)
|
||||
_generate_boot_file (part, &vh.vh_vd[i]);
|
||||
}
|
||||
|
||||
vh.vh_csum = 0;
|
||||
vh.vh_csum = PED_CPU_TO_BE32 (_checksum ((uint32_t*) &vh,
|
||||
sizeof (struct volume_header)));
|
||||
|
||||
return (ptt_write_sector (disk, &vh, sizeof vh)
|
||||
&& ped_device_sync (disk->dev));
|
||||
}
|
||||
#endif /* !DISCOVER_ONLY */
|
||||
|
||||
static PedPartition*
|
||||
dvh_partition_new (const PedDisk* disk, PedPartitionType part_type,
|
||||
const PedFileSystemType* fs_type,
|
||||
PedSector start, PedSector end)
|
||||
{
|
||||
PedPartition* part;
|
||||
DVHPartData* dvh_part_data;
|
||||
|
||||
part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
|
||||
if (!part)
|
||||
goto error;
|
||||
|
||||
if (!ped_partition_is_active (part)) {
|
||||
part->disk_specific = NULL;
|
||||
return part;
|
||||
}
|
||||
|
||||
dvh_part_data = part->disk_specific =
|
||||
ped_malloc (sizeof (DVHPartData));
|
||||
if (!dvh_part_data)
|
||||
goto error_free_part;
|
||||
|
||||
dvh_part_data->type = (part_type == PED_PARTITION_EXTENDED)
|
||||
? PTYPE_VOLHDR
|
||||
: PTYPE_RAW;
|
||||
strcpy (dvh_part_data->name, "");
|
||||
dvh_part_data->real_file_size = part->geom.length * 512;
|
||||
return part;
|
||||
|
||||
error_free_part:
|
||||
_ped_partition_free (part);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PedPartition*
|
||||
dvh_partition_duplicate (const PedPartition* part)
|
||||
{
|
||||
PedPartition* result;
|
||||
DVHPartData* part_data = part->disk_specific;
|
||||
DVHPartData* result_data;
|
||||
|
||||
result = _ped_partition_alloc (part->disk, part->type, part->fs_type,
|
||||
part->geom.start, part->geom.end);
|
||||
if (!result)
|
||||
goto error;
|
||||
result->num = part->num;
|
||||
|
||||
if (!ped_partition_is_active (part)) {
|
||||
result->disk_specific = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
result_data = result->disk_specific =
|
||||
ped_malloc (sizeof (DVHPartData));
|
||||
if (!result_data)
|
||||
goto error_free_part;
|
||||
|
||||
result_data->type = part_data->type;
|
||||
strcpy (result_data->name, part_data->name);
|
||||
result_data->real_file_size = part_data->real_file_size;
|
||||
return result;
|
||||
|
||||
error_free_part:
|
||||
_ped_partition_free (result);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dvh_partition_destroy (PedPartition* part)
|
||||
{
|
||||
if (ped_partition_is_active (part)) {
|
||||
PED_ASSERT (part->disk_specific != NULL);
|
||||
free (part->disk_specific);
|
||||
}
|
||||
_ped_partition_free (part);
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
|
||||
{
|
||||
DVHPartData* dvh_part_data = part->disk_specific;
|
||||
|
||||
part->fs_type = fs_type;
|
||||
|
||||
if (part->type == PED_PARTITION_EXTENDED) {
|
||||
dvh_part_data->type = PTYPE_VOLHDR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Is this a bootfile? */
|
||||
if (part->type == PED_PARTITION_LOGICAL)
|
||||
return 1;
|
||||
|
||||
if (fs_type && !strcmp (fs_type->name, "xfs"))
|
||||
dvh_part_data->type = PTYPE_XFS;
|
||||
else
|
||||
dvh_part_data->type = PTYPE_RAW;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
|
||||
{
|
||||
DVHDiskData* dvh_disk_data = part->disk->disk_specific;
|
||||
|
||||
switch (flag) {
|
||||
case PED_PARTITION_ROOT:
|
||||
if (part->type != 0 && state) {
|
||||
#ifndef DISCOVER_ONLY
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("Only primary partitions can be root "
|
||||
"partitions."));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
dvh_disk_data->root = state ? part->num : 0;
|
||||
break;
|
||||
|
||||
case PED_PARTITION_SWAP:
|
||||
if (part->type != 0 && state) {
|
||||
#ifndef DISCOVER_ONLY
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("Only primary partitions can be swap "
|
||||
"partitions."));
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
dvh_disk_data->swap = state ? part->num : 0;
|
||||
break;
|
||||
|
||||
case PED_PARTITION_BOOT:
|
||||
if (part->type != PED_PARTITION_LOGICAL && state) {
|
||||
#ifndef DISCOVER_ONLY
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("Only logical partitions can be a boot "
|
||||
"file."));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
dvh_disk_data->boot = state ? part->num : 0;
|
||||
break;
|
||||
|
||||
case PED_PARTITION_LVM:
|
||||
case PED_PARTITION_LBA:
|
||||
case PED_PARTITION_HIDDEN:
|
||||
case PED_PARTITION_RAID:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _GL_ATTRIBUTE_PURE
|
||||
dvh_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
|
||||
{
|
||||
DVHDiskData* dvh_disk_data = part->disk->disk_specific;
|
||||
|
||||
switch (flag) {
|
||||
case PED_PARTITION_ROOT:
|
||||
return dvh_disk_data->root == part->num;
|
||||
|
||||
case PED_PARTITION_SWAP:
|
||||
return dvh_disk_data->swap == part->num;
|
||||
|
||||
case PED_PARTITION_BOOT:
|
||||
return dvh_disk_data->boot == part->num;
|
||||
|
||||
case PED_PARTITION_LVM:
|
||||
case PED_PARTITION_LBA:
|
||||
case PED_PARTITION_HIDDEN:
|
||||
case PED_PARTITION_RAID:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_partition_is_flag_available (const PedPartition* part,
|
||||
PedPartitionFlag flag)
|
||||
{
|
||||
switch (flag) {
|
||||
case PED_PARTITION_ROOT:
|
||||
case PED_PARTITION_SWAP:
|
||||
case PED_PARTITION_BOOT:
|
||||
return 1;
|
||||
|
||||
case PED_PARTITION_LVM:
|
||||
case PED_PARTITION_LBA:
|
||||
case PED_PARTITION_HIDDEN:
|
||||
case PED_PARTITION_RAID:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
dvh_partition_set_name (PedPartition* part, const char* name)
|
||||
{
|
||||
DVHPartData* dvh_part_data = part->disk_specific;
|
||||
|
||||
if (part->type == PED_PARTITION_LOGICAL) {
|
||||
/* Bootfile */
|
||||
memcpy (dvh_part_data->name, name, VDNAMESIZE);
|
||||
dvh_part_data->name[VDNAMESIZE] = 0;
|
||||
} else {
|
||||
#ifndef DISCOVER_ONLY
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("failed to set dvh partition name to %s:\n"
|
||||
"Only logical partitions (boot files) have a name."),
|
||||
name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static const char*
|
||||
dvh_partition_get_name (const PedPartition* part)
|
||||
{
|
||||
DVHPartData* dvh_part_data = part->disk_specific;
|
||||
return dvh_part_data->name;
|
||||
}
|
||||
|
||||
/* The constraint for the volume header partition is different, because it must
|
||||
* contain the first sector of the disk.
|
||||
*/
|
||||
static PedConstraint*
|
||||
_get_extended_constraint (PedDisk* disk)
|
||||
{
|
||||
PedGeometry min_geom;
|
||||
if (!ped_geometry_init (&min_geom, disk->dev, 0, 1))
|
||||
return NULL;
|
||||
return ped_constraint_new_from_min (&min_geom);
|
||||
}
|
||||
|
||||
static PedConstraint*
|
||||
_get_primary_constraint (PedDisk* disk)
|
||||
{
|
||||
PedGeometry max_geom;
|
||||
if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
|
||||
return NULL;
|
||||
return ped_constraint_new_from_max (&max_geom);
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_partition_align (PedPartition* part, const PedConstraint* constraint)
|
||||
{
|
||||
PED_ASSERT (part != NULL);
|
||||
|
||||
if (_ped_partition_attempt_align (
|
||||
part, constraint,
|
||||
(part->type == PED_PARTITION_EXTENDED)
|
||||
? _get_extended_constraint (part->disk)
|
||||
: _get_primary_constraint (part->disk)))
|
||||
return 1;
|
||||
|
||||
#ifndef DISCOVER_ONLY
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("Unable to satisfy all constraints on the partition."));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_partition_enumerate (PedPartition* part)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* never change the partition numbers */
|
||||
if (part->num != -1)
|
||||
return 1;
|
||||
|
||||
_flush_stale_flags (part->disk);
|
||||
|
||||
if (part->type & PED_PARTITION_LOGICAL) {
|
||||
/* Bootfile */
|
||||
for (i = 1 + NPARTAB; i <= NPARTAB + NVDIR; i++) {
|
||||
if (!ped_disk_get_partition (part->disk, i)) {
|
||||
part->num = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
PED_ASSERT (0);
|
||||
} else if (part->type & PED_PARTITION_EXTENDED) {
|
||||
/* Volheader */
|
||||
part->num = PNUM_VOLHDR + 1;
|
||||
} else {
|
||||
for (i = 1; i <= NPARTAB; i++) {
|
||||
/* reserved for full volume partition */
|
||||
if (i == PNUM_VOLUME + 1)
|
||||
continue;
|
||||
|
||||
if (!ped_disk_get_partition (part->disk, i)) {
|
||||
part->num = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("Too many primary partitions"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dvh_get_max_primary_partition_count (const PedDisk* disk)
|
||||
{
|
||||
return NPARTAB;
|
||||
}
|
||||
|
||||
static bool
|
||||
dvh_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
|
||||
{
|
||||
*max_n = NPARTAB;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dvh_alloc_metadata (PedDisk* disk)
|
||||
{
|
||||
PedPartition* part;
|
||||
PedPartition* extended_part;
|
||||
PedPartitionType metadata_type;
|
||||
PED_ASSERT(disk != NULL);
|
||||
|
||||
/* We don't need to "protect" the start of the disk from the volume
|
||||
* header.
|
||||
*/
|
||||
extended_part = ped_disk_extended_partition (disk);
|
||||
if (extended_part && extended_part->geom.start == 0)
|
||||
metadata_type = PED_PARTITION_METADATA | PED_PARTITION_LOGICAL;
|
||||
else
|
||||
metadata_type = PED_PARTITION_METADATA;
|
||||
|
||||
part = ped_partition_new (disk, metadata_type, NULL, 0, 0);
|
||||
if (!part)
|
||||
goto error;
|
||||
|
||||
PedConstraint *constraint_exact
|
||||
= ped_constraint_exact (&part->geom);
|
||||
bool ok = ped_disk_add_partition (disk, part, constraint_exact);
|
||||
ped_constraint_destroy (constraint_exact);
|
||||
if (ok)
|
||||
return 1;
|
||||
|
||||
ped_partition_destroy (part);
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "pt-common.h"
|
||||
PT_define_limit_functions (dvh)
|
||||
|
||||
static PedDiskOps dvh_disk_ops = {
|
||||
clobber: NULL,
|
||||
write: NULL_IF_DISCOVER_ONLY (dvh_write),
|
||||
|
||||
partition_set_name: dvh_partition_set_name,
|
||||
partition_get_name: dvh_partition_get_name,
|
||||
PT_op_function_initializers (dvh)
|
||||
};
|
||||
|
||||
static PedDiskType dvh_disk_type = {
|
||||
next: NULL,
|
||||
name: "dvh",
|
||||
ops: &dvh_disk_ops,
|
||||
features: PED_DISK_TYPE_PARTITION_NAME | PED_DISK_TYPE_EXTENDED
|
||||
};
|
||||
|
||||
void
|
||||
ped_disk_dvh_init ()
|
||||
{
|
||||
PED_ASSERT (sizeof (struct volume_header) == 512);
|
||||
|
||||
ped_disk_type_register (&dvh_disk_type);
|
||||
}
|
||||
|
||||
void
|
||||
ped_disk_dvh_done ()
|
||||
{
|
||||
ped_disk_type_unregister (&dvh_disk_type);
|
||||
}
|
||||
Reference in New Issue
Block a user