mac.c revision 7e7bd3dccbfe8f79e25e5c1554b5bc3a9aaca321
/*
libparted - a library for manipulating disk partitions
Copyright (C) 2000, 2002, 2004, 2007 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>
#if ENABLE_NLS
# include <libintl.h>
#else
#endif /* ENABLE_NLS */
/* 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;
return 0;
return _check_signature (&buf);
}
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)
goto error;
/* remove the partition map partition - it will be duplicated
* later.
*/
/* ugly, but C is ugly :p */
return new_disk;
return NULL;
}
static void
{
}
#ifndef DISCOVER_ONLY
static int
{
return 0;
if (!_rawpart_check_signature (&raw_part))
return 1;
return 0;
}
}
static int
{
return 0;
if (!_check_signature (&raw_disk))
return 0;
return 0;
return _clobber_part_map (dev);
}
#endif /* !DISCOVER_ONLY */
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
{
int i;
for (i = 1; i < 64; i *= 2) {
return 0;
if (_rawpart_check_signature (&raw_part)
&& !_rawpart_is_void (&raw_part)) {
mac_disk_data->ghost_size = i;
return 0);
return 1;
}
}
#ifndef DISCOVER_ONLY
_("No valid partition map found."));
#endif
return 0;
}
static int
{
int num;
int last_part_entry_num = 0;
goto error;
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;
&ghost_entry, sizeof (MacRawPartition));
return 1;
}
static void
{
for (i = 0; i < count_orig; i++) {
break;
}
}
}
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;
return i;
}
return 0;
}
static int
{
return 0;
sizeof(raw_disk.driverlist));
}
static int
{
int num;
goto error;
}
if (!mac_driverdata)
goto error;
part_map = (MacRawPartition*)
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 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 0;
}
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 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 PedDiskOps mac_disk_ops = {
#ifndef DISCOVER_ONLY
.clobber = mac_clobber,
#else
#endif
#ifndef DISCOVER_ONLY
/* FIXME: remove this cast, once mac_write is fixed not to
modify its *DISK parameter. */
#else
#endif
};
static PedDiskType mac_disk_type = {
.name = "mac",
.ops = &mac_disk_ops,
};
void
{
}
void
{
}