mac.c revision 1
/*
libparted - a library for manipulating disk partitions
Copyright (C) 2000, 2002, 2004, 2007-2010 Free Software Foundation,
Inc.
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 <stdbool.h>
#if ENABLE_NLS
# include <libintl.h>
#else
#endif /* ENABLE_NLS */
#include "misc.h"
#include "pt-tools.h"
/* struct's hacked from Linux source: fs/partitions/mac.h
* I believe it was originally written by Paul Mackerras (from comments in
* Quik source)
*
* See also:
*
* Partition types:
* Apple_Bootstrap new-world (HFS) boot partition
* Apple_partition_map partition map (table)
* Apple_Driver device driver
* Apple_Driver43 SCSI Manager 4.3 device driver
* Apple_MFS original Macintosh File System
* Apple_HFS Hierarchical File System (and +)
* Apple_HFSX HFS+ with case sensitivity and more
* Apple_UNIX_SVR2 UNIX file system (UFS?)
* Apple_PRODOS ProDOS file system
* Apple_Free unused space
* Apple_Scratch empty
* Apple_Void padding for iso9660
* Apple_Extra an unused partition map entry
*
* Quick explanation:
* ------------------
* Terminology:
*
* Parted Apple
* ------ -----
* disk no equivalent.
* partition volume or partition
* sector block
*
* * All space must be accounted for, except block 0 (driver block) and
* block 1-X (the partition map: i.e. lots of MacRawPartitions)
*
* entries in the partition map, because the first partition starts
* immediately after the partition map. When we can move the start of
* HFS and ext2 partitions, this problem will disappear ;-)
*/
#define MAC_PARTITION_MAGIC_2 0x504d
#define MAC_DISK_MAGIC 0x4552
typedef struct _MacRawPartition MacRawPartition;
typedef struct _MacRawDisk MacRawDisk;
typedef struct _MacDeviceDriver MacDeviceDriver;
typedef struct _MacPartitionData MacPartitionData;
typedef struct _MacDiskData MacDiskData;
#ifdef __sun
#define __attribute__(X) /*nothing*/
#endif /* __sun */
#ifdef __sun
#pragma pack(1)
#endif
char _padding[372];
};
/* Driver descriptor structure, in block 0 */
};
};
#ifdef __sun
#pragma pack()
#endif
struct _MacPartitionData {
char processor_name[17];
int is_boot;
int is_driver;
int has_driver;
int is_root;
int is_swap;
int is_lvm;
int is_raid;
};
struct _MacDiskData {
int ghost_size; /* sectors per "driver" block */
int part_map_entry_count; /* # entries (incl. ghost) */
int part_map_entry_num; /* partition map location */
int active_part_entry_count; /* # real partitions */
int free_part_entry_count; /* # free space */
int last_part_entry_num; /* last entry number */
};
static PedDiskType mac_disk_type;
static int
{
#ifdef DISCOVER_ONLY
return 0;
#else
return ped_exception_throw (
_("Invalid signature %x for Mac disk labels."),
#endif
}
return 1;
}
static int
{
}
static int
{
return 0;
void *label;
return 0;
return valid;
}
static int
{
#ifndef DISCOVER_ONLY
if (warn && ped_exception_throw (
_("Partition map has no partition map entry!"))
goto error;
#endif /* !DISCOVER_ONLY */
if (part_map_size == 0)
part_map_size = 64;
if (!new_part)
goto error;
goto error_destroy_new_part;
return 1;
return 0;
}
static PedDisk*
{
#ifndef DISCOVER_ONLY
_("%s is too small for a Mac disk label!"),
goto error;
}
#endif
if (!disk)
goto error;
if (!mac_disk_data)
goto error_free_disk;
mac_disk_data->block_size = 0;
mac_disk_data->driver_count = 0;
if (!_disk_add_part_map_entry (disk, 0))
goto error_free_disk;
return disk;
return NULL;
}
static PedDisk*
{
if (!new_disk)
return NULL;
/* remove the partition map partition - it will be duplicated
* later.
*/
/* ped_disk_remove_partition may be used only to delete a "normal"
partition. Trying to delete at least "freespace" or "metadata"
partitions leads to a violation of assumptions in
ped_disk_remove_partition, since it calls _disk_push_update_mode,
which destroys all "freespace" and "metadata" partitions, and
depends on that destruction not freeing its PART parameter. */
/* ugly, but C is ugly :p */
return new_disk;
}
static void
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
int i;
for (i = 0; haystack[i] && i < n - needle_size; i++) {
return 1;
}
return 0;
}
static int
{
return 1;
return 1;
return 0;
}
static int
{
return 0;
return 0;
return 1;
}
static int
{
for (i = 0; i < mac_disk_data->driver_count; i++) {
return 1;
driverlist++;
}
return 0;
}
static int
{
return 0;
return 0;
return 1;
}
static int
{
return 0;
return 0;
return 1;
}
static int
{
return 0;
return 1;
}
static int
{
return 0;
return 1;
}
static int
{
}
/* returns 1 if the raw_part represents a partition that is "unused space", or
* doesn't represent a partition at all. NOTE: some people make Apple_Free
* partitions with MacOS, because they can't select another type. So, if the
* name is anything other than "Extra" or "", it is treated as a "real"
* partition.
*/
static int
{
return 0;
return 0;
return 0;
return 0;
return 1;
}
static PedPartition*
{
if (!_rawpart_check_signature (raw_part)) {
#ifndef DISCOVER_ONLY
if (ped_exception_throw (
_("Partition %d has an invalid signature %x."),
num,
#endif
goto error;
}
if (length == 0) {
#ifndef DISCOVER_ONLY
_("Partition %d has an invalid length of 0 bytes!"),
num);
#endif
return NULL;
}
if (!part)
goto error;
if (mac_part_data->is_driver)
/* "data" region */
#ifndef DISCOVER_ONLY
if (raw_part->data_start) {
_("The data region doesn't start at the start "
"of the partition."));
goto error_destroy_part;
}
#endif /* !DISCOVER_ONLY */
/* boot region - we have no idea what this is for, but Mac OSX
* seems to put garbage here, and doesn't pay any attention to
* it afterwards. [clausen, dan burcaw]
*/
#if 0
if (raw_part->boot_start) {
_("The boot region doesn't start at the start "
"of the partition."));
goto error_destroy_part;
}
#endif
#ifndef DISCOVER_ONLY
if (mac_part_data->has_driver) {
if (ped_exception_throw (
_("The partition's boot region doesn't occupy "
"the entire partition."))
goto error_destroy_part;
}
} else {
!mac_part_data->is_boot) {
if (ped_exception_throw (
_("The partition's data region doesn't occupy "
"the entire partition."))
goto error_destroy_part;
}
}
#endif /* !DISCOVER_ONLY */
return part;
return NULL;
}
/* looks at the partition map size field in a mac raw partition, and calculates
* what the size of the partition map should be, from it
*/
static int
{
}
static int
{
#ifndef DISCOVER_ONLY
_("Weird block size on device descriptor: %d bytes is "
"not divisible by 512."),
#endif
goto error;
}
#ifndef DISCOVER_ONLY
if (ped_exception_throw (
_("The driver descriptor says the physical block size "
"is %d bytes, but Linux says it is %d bytes."),
(int) block_size * 512,
goto error;
#endif
}
return 1;
return 0;
}
/* Tries to figure out the block size used by the drivers, for the ghost
* partitioning scheme. Ghost partitioning works like this: the OpenFirmware
* (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
* perhaps, some other number?). To remain compatible, the partition map
* only has "real" partition map entries on ghost-aligned block numbers (and
* the others are padded with Apple_Void partitions). This function tries
* to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
* doesn't always equal 2048!!!)
*/
static int
{
if (!buf)
return 0;
int i;
int found = 0;
for (i = 1; i < 64; i *= 2) {
break;
if (_rawpart_check_signature (buf)
&& !_rawpart_is_void (buf)) {
mac_disk_data->ghost_size = i;
found = 1;
break;
}
}
#ifndef DISCOVER_ONLY
if (!found)
_("No valid partition map found."));
#endif
return found;
}
static int
{
int num;
int last_part_entry_num = 0;
void *buf;
return 0;
if (!_check_signature (raw_disk))
goto error;
goto error;
if (!_disk_analyse_ghost_size (disk))
goto error;
if (!ped_disk_delete_all (disk))
goto error;
sizeof(mac_disk_data->driverlist));
}
goto error_delete_all;
if (!_rawpart_check_signature (raw_part))
continue;
if (num == 1)
!= last_part_entry_num) {
if (ped_exception_throw (
_("Conflicting partition map entry sizes! "
"Entry 1 says it is %d, but entry %d says "
"it is %d!"),
goto error_delete_all;
}
if (!_rawpart_is_active (raw_part))
continue;
if (!part)
goto error_delete_all;
goto error_delete_all;
if (_rawpart_is_partition_map (raw_part)) {
&& ped_exception_throw (
_("Weird! There are 2 partitions "
"map entries!"))
goto error_delete_all;
}
}
if (!mac_disk_data->part_map_entry_num) {
goto error_delete_all;
}
return 1;
return 0;
}
#ifndef DISCOVER_ONLY
/* The Ghost partition: is a blank entry, used to pad out each block (where
* there physical block size > 512 bytes). This is because OpenFirmware uses
* 512 byte blocks, but device drivers Think Different TM, with a different
* lbock size, so we need to do this to avoid a clash (!)
*/
static int
{
int i;
if (!buf)
return 0;
}
return 1;
}
static void
{
for (i = 0; i < count_orig; i++) {
break;
}
}
}
static MacRawPartition *
{
return (MacRawPartition *) ((char*)part_map
}
/* Initialize the disk->dev->sector_size bytes of part_map[part->num]. */
static int
{
if (mac_part_data->is_driver) {
if (mac_part_data->has_driver)
} else
goto error;
return 1;
return 0;
}
static int
{
part_map_entry->status = 0;
part_map_entry->driver_sig = 0;
goto error;
return 1;
return 0;
}
static int
{
PED_ASSERT (num > 0, return 0);
}
/* returns the first empty entry in the partition map */
static int
{
int i;
if (!part_map_entry->signature)
return i;
}
return 0;
}
static int
{
void *s0;
return 0;
sizeof(raw_disk->driverlist));
return write_ok;
}
static int
{
int num;
goto error;
}
if (!mac_driverdata)
goto error;
if (!part_map)
goto error_free_driverdata;
/* write (to memory) the "real" partitions */
if (!ped_partition_is_active (part))
continue;
goto error_free_part_map;
}
/* write the "free space" partitions */
continue;
part_map))
goto error_free_part_map;
}
/* write the "void" (empty) partitions */
/* write to disk */
goto error_free_part_map;
return write_ok;
return 0;
}
#endif /* !DISCOVER_ONLY */
static PedPartition*
{
if (!part)
goto error;
if (ped_partition_is_active (part)) {
if (!mac_data)
goto error_free_part;
} else {
}
return part;
return NULL;
}
static PedPartition*
{
if (!new_part)
return NULL;
/* ugly, but C is ugly :p */
return new_part;
}
static void
{
if (ped_partition_is_active (part))
}
static int
{
return 1;
}
} else {
}
return 1;
}
static int
{
switch (flag) {
case PED_PARTITION_BOOT:
if (state) {
}
return 1;
case PED_PARTITION_ROOT:
if (state) {
} else {
}
return 1;
case PED_PARTITION_SWAP:
if (state) {
} else {
}
return 1;
case PED_PARTITION_LVM:
if (state) {
} else {
}
return 1;
case PED_PARTITION_RAID:
if (state) {
} else {
}
return 1;
default:
return 0;
}
}
static int
{
switch (flag) {
case PED_PARTITION_BOOT:
case PED_PARTITION_ROOT:
case PED_PARTITION_SWAP:
case PED_PARTITION_LVM:
case PED_PARTITION_RAID:
default:
return 0;
}
}
static int
{
switch (flag) {
case PED_PARTITION_BOOT:
case PED_PARTITION_ROOT:
case PED_PARTITION_SWAP:
case PED_PARTITION_LVM:
case PED_PARTITION_RAID:
return 1;
default:
return 0;
}
}
static void
{
int i;
#ifndef DISCOVER_ONLY
if (ped_exception_throw (
_("Changing the name of a root or swap partition "
"will prevent Linux from recognising it as such."))
return;
}
#endif
mac_data->volume_name [i] = 0;
}
static const char*
{
return mac_data->volume_name;
}
static PedAlignment*
{
return ped_alignment_new(0, sector_size);
}
static PedConstraint*
{
return NULL;
return NULL;
return NULL;
}
static int
{
return 1;
#ifndef DISCOVER_ONLY
_("Unable to satisfy all constraints on the partition."));
#endif
return 0;
}
static int
{
int i;
int max_part_count;
return 1;
for (i = 1; i <= max_part_count; i++) {
if (!ped_disk_get_partition (disk, i)) {
return 1;
}
}
#ifndef DISCOVER_ONLY
_("Can't add another partition -- the partition map is too "
"small!"));
#endif
return 0;
}
static int
{
/* subtle: we only care about free space after the partition map.
* the partition map is an "active" partition, BTW... */
if (!ped_partition_is_active (part))
continue;
}
return 1;
}
static int
{
if (!new_part)
goto error;
goto error_destroy_new_part;
return 1;
return 0;
}
static int
{
return 0;
/* hack: this seems to be a good place, to update the partition map
* entry count, since mac_alloc_metadata() gets called during
* _disk_pop_update_mode()
*/
return _disk_count_partitions (disk);
}
static int
{
/* HACK: if we haven't found the partition map partition (yet),
* we return this.
*/
if (!part_map_partition) {
return 65536;
}
/* HACK: since Mac labels need an entry for free-space regions, we
* must allow half plus 1 entries for free-space partitions. I hate
* this, but things get REALLY complicated, otherwise.
* (I'm prepared to complicate things later, but I want to get
* everything working, first)
*/
}
static bool
{
*max_n = 65536;
return true;
}
#include "pt-common.h"
static PedDiskOps mac_disk_ops = {
/* FIXME: remove this cast, once mac_write is fixed not to
modify its *DISK parameter. */
};
static PedDiskType mac_disk_type = {
.name = "mac",
.ops = &mac_disk_ops,
};
void
{
}
void
{
}