~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to libparted/labels/mac.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    libparted - a library for manipulating disk partitions
 
3
    Copyright (C) 2000, 2002, 2004, 2007-2012 Free Software Foundation, Inc.
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
 
 
19
#include <config.h>
 
20
 
 
21
#include <parted/parted.h>
 
22
#include <parted/debug.h>
 
23
#include <parted/endian.h>
 
24
#include <stdbool.h>
 
25
 
 
26
#if ENABLE_NLS
 
27
#  include <libintl.h>
 
28
#  define _(String) dgettext (PACKAGE, String)
 
29
#else
 
30
#  define _(String) (String)
 
31
#endif /* ENABLE_NLS */
 
32
 
 
33
#include "misc.h"
 
34
#include "pt-tools.h"
 
35
 
 
36
/* struct's hacked from Linux source:  fs/partitions/mac.h
 
37
 * I believe it was originally written by Paul Mackerras (from comments in
 
38
 * Quik source)
 
39
 *
 
40
 * See also:
 
41
 *      http://developer.apple.com/documentation/mac/Devices/Devices-126.html
 
42
 *      http://developer.apple.com/documentation/mac/Devices/Devices-121.html
 
43
 *      http://devworld.apple.com/technotes/tn/tn1189.html
 
44
 *
 
45
 * Partition types:
 
46
 *      Apple_Bootstrap         new-world (HFS) boot partition
 
47
 *      Apple_partition_map     partition map (table)
 
48
 *      Apple_Driver            device driver
 
49
 *      Apple_Driver43          SCSI Manager 4.3 device driver
 
50
 *      Apple_MFS               original Macintosh File System
 
51
 *      Apple_HFS               Hierarchical File System (and +)
 
52
 *      Apple_HFSX              HFS+ with case sensitivity and more
 
53
 *      Apple_UNIX_SVR2         UNIX file system (UFS?)
 
54
 *      Apple_PRODOS            ProDOS file system
 
55
 *      Apple_Free              unused space
 
56
 *      Apple_Scratch           empty
 
57
 *      Apple_Void              padding for iso9660
 
58
 *      Apple_Extra             an unused partition map entry
 
59
 *
 
60
 * Quick explanation:
 
61
 * ------------------
 
62
 * Terminology:
 
63
 *
 
64
 *      Parted                  Apple
 
65
 *      ------                  -----
 
66
 *      device                  disk/device
 
67
 *      disk                    no equivalent.
 
68
 *      partition               volume or partition
 
69
 *      sector                  block
 
70
 *
 
71
 *      * All space must be accounted for, except block 0 (driver block) and
 
72
 *      block 1-X (the partition map: i.e. lots of MacRawPartitions)
 
73
 *
 
74
 *      * It's really hard to grow/shrink the number of MacRawPartition
 
75
 *      entries in the partition map, because the first partition starts
 
76
 *      immediately after the partition map.  When we can move the start of
 
77
 *      HFS and ext2 partitions, this problem will disappear ;-)
 
78
 */
 
79
 
 
80
#define MAC_PARTITION_MAGIC_1   0x5453          /* old */
 
81
#define MAC_PARTITION_MAGIC_2   0x504d
 
82
#define MAC_DISK_MAGIC          0x4552
 
83
 
 
84
#define MAC_STATUS_BOOTABLE     8       /* partition is bootable */
 
85
 
 
86
typedef struct _MacRawPartition     MacRawPartition;
 
87
typedef struct _MacRawDisk          MacRawDisk;
 
88
typedef struct _MacDeviceDriver     MacDeviceDriver;
 
89
typedef struct _MacPartitionData    MacPartitionData;
 
90
typedef struct _MacDiskData         MacDiskData;
 
91
 
 
92
struct __attribute__ ((packed)) _MacRawPartition {
 
93
        uint16_t        signature;      /* expected to be MAC_PARTITION_MAGIC */
 
94
        uint16_t        res1;
 
95
        uint32_t        map_count;      /* # blocks in partition map */
 
96
        uint32_t        start_block;    /* absolute starting block # of partition */
 
97
        uint32_t        block_count;    /* number of blocks in partition */
 
98
        char            name[32];       /* partition name */
 
99
        char            type[32];       /* string type description */
 
100
        uint32_t        data_start;     /* rel block # of first data block */
 
101
        uint32_t        data_count;     /* number of data blocks */
 
102
        uint32_t        status;         /* partition status bits */
 
103
        uint32_t        boot_start;
 
104
        uint32_t        boot_count;
 
105
        uint32_t        boot_load;
 
106
        uint32_t        boot_load2;
 
107
        uint32_t        boot_entry;
 
108
        uint32_t        boot_entry2;
 
109
        uint32_t        boot_cksum;
 
110
        char            processor[16];  /* Contains 680x0, x=0,2,3,4; or empty */
 
111
        uint32_t        driver_sig;
 
112
        char            _padding[372];
 
113
};
 
114
 
 
115
/* Driver descriptor structure, in block 0 */
 
116
struct __attribute__ ((packed)) _MacRawDisk {
 
117
        uint16_t        signature;      /* expected to be MAC_DRIVER_MAGIC */
 
118
        uint16_t        block_size;     /* physical sector size */
 
119
        uint32_t        block_count;    /* size of device in blocks */
 
120
        uint16_t        dev_type;       /* reserved */
 
121
        uint16_t        dev_id;         /* reserved */
 
122
        uint32_t        data;           /* reserved */
 
123
        uint16_t        driver_count;   /* # of driver descriptor entries */
 
124
        uint8_t         driverlist[488];/* info about available drivers */
 
125
        uint16_t        padding[3];     /* pad to 512 bytes */
 
126
};
 
127
 
 
128
struct __attribute__ ((packed)) _MacDeviceDriver {
 
129
        uint32_t        block;          /* startblock in MacRawDisk->block_size units */
 
130
        uint16_t        size;           /* size in 512 byte units */
 
131
        uint16_t        type;           /* operating system type (MacOS = 1) */
 
132
};
 
133
 
 
134
struct _MacPartitionData {
 
135
        char            volume_name[33];        /* eg: "Games" */
 
136
        char            system_name[33];        /* eg: "Apple_Unix_SVR2" */
 
137
        char            processor_name[17];
 
138
 
 
139
        int             is_boot;
 
140
        int             is_driver;
 
141
        int             has_driver;
 
142
        int             is_root;
 
143
        int             is_swap;
 
144
        int             is_lvm;
 
145
        int             is_raid;
 
146
 
 
147
        PedSector       data_region_length;
 
148
        PedSector       boot_region_length;
 
149
 
 
150
        uint32_t        boot_base_address;
 
151
        uint32_t        boot_entry_address;
 
152
        uint32_t        boot_checksum;
 
153
 
 
154
        uint32_t        status;
 
155
        uint32_t        driver_sig;
 
156
};
 
157
 
 
158
struct _MacDiskData {
 
159
        int             ghost_size;             /* sectors per "driver" block */
 
160
        int             part_map_entry_count;   /* # entries (incl. ghost) */
 
161
        int             part_map_entry_num;     /* partition map location */
 
162
 
 
163
        int             active_part_entry_count;        /* # real partitions */
 
164
        int             free_part_entry_count;          /* # free space */
 
165
        int             last_part_entry_num;            /* last entry number */
 
166
 
 
167
        uint16_t        block_size;             /* physical sector size */
 
168
        uint16_t        driver_count;
 
169
        MacDeviceDriver driverlist[1 + 60];     /* 488 bytes */
 
170
};
 
171
 
 
172
static PedDiskType mac_disk_type;
 
173
 
 
174
static int
 
175
_check_signature (MacRawDisk const *raw_disk)
 
176
{
 
177
        if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
 
178
#ifdef DISCOVER_ONLY
 
179
                return 0;
 
180
#else
 
181
                return ped_exception_throw (
 
182
                        PED_EXCEPTION_ERROR,
 
183
                        PED_EXCEPTION_IGNORE_CANCEL,
 
184
                        _("Invalid signature %x for Mac disk labels."),
 
185
                        (int) PED_BE16_TO_CPU (raw_disk->signature))
 
186
                        == PED_EXCEPTION_IGNORE;
 
187
#endif
 
188
        }
 
189
 
 
190
        return 1;
 
191
}
 
192
 
 
193
static int
 
194
_rawpart_check_signature (MacRawPartition* raw_part)
 
195
{
 
196
        int     sig = (int) PED_BE16_TO_CPU (raw_part->signature);
 
197
        return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
 
198
}
 
199
 
 
200
static int
 
201
mac_probe (const PedDevice * dev)
 
202
{
 
203
        PED_ASSERT (dev != NULL);
 
204
 
 
205
        if (dev->sector_size < sizeof (MacRawDisk))
 
206
                return 0;
 
207
 
 
208
        void *label;
 
209
        if (!ptt_read_sector (dev, 0, &label))
 
210
                return 0;
 
211
 
 
212
        int valid = _check_signature (label);
 
213
 
 
214
        free (label);
 
215
        return valid;
 
216
}
 
217
 
 
218
static int
 
219
_disk_add_part_map_entry (PedDisk* disk, int warn)
 
220
{
 
221
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
222
        PedPartition*           new_part;
 
223
        MacPartitionData*       mac_part_data;
 
224
        PedSector               part_map_size;
 
225
        PedConstraint*          constraint_any = ped_constraint_any (disk->dev);
 
226
 
 
227
#ifndef DISCOVER_ONLY
 
228
        if (warn && ped_exception_throw (
 
229
                PED_EXCEPTION_ERROR,
 
230
                PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
 
231
                _("Partition map has no partition map entry!"))
 
232
                        != PED_EXCEPTION_FIX)
 
233
                goto error;
 
234
#endif /* !DISCOVER_ONLY */
 
235
 
 
236
        part_map_size
 
237
                = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
 
238
        if (part_map_size == 0)
 
239
                part_map_size = 64;
 
240
 
 
241
        new_part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
 
242
                                      1, part_map_size - 1);
 
243
        if (!new_part)
 
244
                goto error;
 
245
 
 
246
        mac_part_data = new_part->disk_specific;
 
247
        strcpy (mac_part_data->volume_name, "Apple");
 
248
        strcpy (mac_part_data->system_name, "Apple_partition_map");
 
249
 
 
250
        if (!ped_disk_add_partition (disk, new_part, constraint_any))
 
251
                goto error_destroy_new_part;
 
252
 
 
253
        mac_disk_data->part_map_entry_num = new_part->num;
 
254
        mac_disk_data->part_map_entry_count
 
255
                = new_part->geom.end - mac_disk_data->ghost_size;
 
256
        ped_constraint_destroy (constraint_any);
 
257
        return 1;
 
258
 
 
259
error_destroy_new_part:
 
260
        ped_partition_destroy (new_part);
 
261
error:
 
262
        ped_constraint_destroy (constraint_any);
 
263
        return 0;
 
264
}
 
265
 
 
266
static PedDisk*
 
267
mac_alloc (const PedDevice* dev)
 
268
{
 
269
        PedDisk*                disk;
 
270
        MacDiskData*            mac_disk_data;
 
271
 
 
272
        PED_ASSERT (dev != NULL);
 
273
 
 
274
#ifndef DISCOVER_ONLY
 
275
        if (dev->length < 256) {
 
276
                ped_exception_throw (
 
277
                        PED_EXCEPTION_ERROR,
 
278
                        PED_EXCEPTION_CANCEL,
 
279
                        _("%s is too small for a Mac disk label!"),
 
280
                        dev->path);
 
281
                goto error;
 
282
        }
 
283
#endif
 
284
 
 
285
        disk = _ped_disk_alloc (dev, &mac_disk_type);
 
286
        if (!disk)
 
287
                goto error;
 
288
 
 
289
        mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
 
290
        if (!mac_disk_data)
 
291
                goto error_free_disk;
 
292
        disk->disk_specific = mac_disk_data;
 
293
        mac_disk_data->ghost_size = disk->dev->sector_size / 512;
 
294
        mac_disk_data->active_part_entry_count = 0;
 
295
        mac_disk_data->free_part_entry_count = 1;
 
296
        mac_disk_data->last_part_entry_num = 1;
 
297
        mac_disk_data->block_size = 0;
 
298
        mac_disk_data->driver_count = 0;
 
299
        memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
 
300
 
 
301
        if (!_disk_add_part_map_entry (disk, 0))
 
302
                goto error_free_disk;
 
303
        return disk;
 
304
 
 
305
error_free_disk:
 
306
        _ped_disk_free (disk);
 
307
error:
 
308
        return NULL;
 
309
}
 
310
 
 
311
static PedDisk*
 
312
mac_duplicate (const PedDisk* disk)
 
313
{
 
314
        PedDisk*        new_disk;
 
315
        MacDiskData*    new_mac_data;
 
316
        MacDiskData*    old_mac_data = (MacDiskData*) disk->disk_specific;
 
317
 
 
318
        new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
 
319
        if (!new_disk)
 
320
                return NULL;
 
321
 
 
322
        new_mac_data = (MacDiskData*) new_disk->disk_specific;
 
323
 
 
324
        /* remove the partition map partition - it will be duplicated
 
325
         * later.
 
326
         */
 
327
        PedSector first_part_map_sector = old_mac_data->ghost_size;
 
328
        PedPartition *partition_map
 
329
          = ped_disk_get_partition_by_sector (new_disk, first_part_map_sector);
 
330
        PED_ASSERT (partition_map != NULL);
 
331
 
 
332
        /* ped_disk_remove_partition may be used only to delete a "normal"
 
333
           partition.  Trying to delete at least "freespace" or "metadata"
 
334
           partitions leads to a violation of assumptions in
 
335
           ped_disk_remove_partition, since it calls _disk_push_update_mode,
 
336
           which destroys all "freespace" and "metadata" partitions, and
 
337
           depends on that destruction not freeing its PART parameter.  */
 
338
        PED_ASSERT (partition_map->type == PED_PARTITION_NORMAL);
 
339
        ped_disk_remove_partition (new_disk, partition_map);
 
340
 
 
341
        /* ugly, but C is ugly :p */
 
342
        memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
 
343
        return new_disk;
 
344
}
 
345
 
 
346
static void
 
347
mac_free (PedDisk* disk)
 
348
{
 
349
        MacDiskData*    mac_disk_data = disk->disk_specific;
 
350
 
 
351
        _ped_disk_free (disk);
 
352
        free (mac_disk_data);
 
353
}
 
354
 
 
355
static int
 
356
_rawpart_cmp_type (const MacRawPartition* raw_part, const char* type)
 
357
{
 
358
        return strncasecmp (raw_part->type, type, 32) == 0;
 
359
}
 
360
 
 
361
static int
 
362
_rawpart_cmp_name (const MacRawPartition* raw_part, const char* name)
 
363
{
 
364
        return strncasecmp (raw_part->name, name, 32) == 0;
 
365
}
 
366
 
 
367
static int
 
368
_rawpart_is_partition_map (const MacRawPartition* raw_part)
 
369
{
 
370
        return _rawpart_cmp_type (raw_part, "Apple_partition_map");
 
371
}
 
372
 
 
373
static int
 
374
strncasestr (const char* haystack, const char* needle, int n)
 
375
{
 
376
        int     needle_size = strlen (needle);
 
377
        int     i;
 
378
 
 
379
        for (i = 0; haystack[i] && i < n - needle_size; i++) {
 
380
                if (strncasecmp (haystack + i, needle, needle_size) == 0)
 
381
                        return 1;
 
382
        }
 
383
 
 
384
        return 0;
 
385
}
 
386
 
 
387
static int
 
388
_rawpart_is_boot (const MacRawPartition* raw_part)
 
389
{
 
390
        if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
 
391
                return 1;
 
392
 
 
393
        if (!strcasecmp(raw_part->type, "Apple_Boot"))
 
394
                return 1;
 
395
 
 
396
        return 0;
 
397
}
 
398
 
 
399
static int
 
400
_rawpart_is_driver (const MacRawPartition* raw_part)
 
401
{
 
402
        if (strncmp (raw_part->type, "Apple_", 6) != 0)
 
403
                return 0;
 
404
        if (!strncasestr (raw_part->type, "driver", 32))
 
405
                return 0;
 
406
        return 1;
 
407
}
 
408
 
 
409
static int _GL_ATTRIBUTE_PURE
 
410
_rawpart_has_driver (const MacRawPartition* raw_part, MacDiskData* mac_disk_data)
 
411
{
 
412
        MacDeviceDriver *driverlist;
 
413
        uint16_t i, bsz;
 
414
        uint32_t driver_bs, driver_be, part_be;
 
415
 
 
416
        driverlist = &mac_disk_data->driverlist[0];
 
417
        bsz = mac_disk_data->block_size / 512;
 
418
        for (i = 0; i < mac_disk_data->driver_count; i++) {
 
419
                driver_bs = driverlist->block * bsz;
 
420
                driver_be = driver_bs + driverlist->size;
 
421
                part_be = raw_part->start_block + raw_part->block_count;
 
422
                if (driver_bs >= raw_part->start_block && driver_be <= part_be)
 
423
                        return 1;
 
424
                driverlist++;
 
425
        }
 
426
        return 0;
 
427
}
 
428
 
 
429
static int
 
430
_rawpart_is_root (MacRawPartition* raw_part)
 
431
{
 
432
        if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
 
433
                return 0;
 
434
        if (strcmp (raw_part->name, "root") != 0)
 
435
                return 0;
 
436
        return 1;
 
437
}
 
438
 
 
439
static int
 
440
_rawpart_is_swap (MacRawPartition* raw_part)
 
441
{
 
442
        if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
 
443
                return 0;
 
444
        if (strcmp (raw_part->name, "swap") != 0)
 
445
                return 0;
 
446
        return 1;
 
447
}
 
448
 
 
449
static int
 
450
_rawpart_is_lvm (MacRawPartition* raw_part)
 
451
{
 
452
        if (strcmp (raw_part->type, "Linux_LVM") != 0)
 
453
                return 0;
 
454
        return 1;
 
455
}
 
456
 
 
457
static int
 
458
_rawpart_is_raid (MacRawPartition* raw_part)
 
459
{
 
460
        if (strcmp (raw_part->type, "Linux_RAID") != 0)
 
461
                return 0;
 
462
        return 1;
 
463
}
 
464
 
 
465
static int
 
466
_rawpart_is_void (MacRawPartition* raw_part)
 
467
{
 
468
        return _rawpart_cmp_type (raw_part, "Apple_Void");
 
469
}
 
470
 
 
471
/* returns 1 if the raw_part represents a partition that is "unused space", or
 
472
 * doesn't represent a partition at all.  NOTE: some people make Apple_Free
 
473
 * partitions with MacOS, because they can't select another type.  So, if the
 
474
 * name is anything other than "Extra" or "", it is treated as a "real"
 
475
 * partition.
 
476
 */
 
477
static int
 
478
_rawpart_is_active (MacRawPartition* raw_part)
 
479
{
 
480
        if (_rawpart_cmp_type (raw_part, "Apple_Free")
 
481
            && (_rawpart_cmp_name (raw_part, "Extra")
 
482
                || _rawpart_cmp_name (raw_part, "")))
 
483
                return 0;
 
484
        if (_rawpart_cmp_type (raw_part, "Apple_Void"))
 
485
                return 0;
 
486
        if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
 
487
                return 0;
 
488
        if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
 
489
                return 0;
 
490
 
 
491
        return 1;
 
492
}
 
493
 
 
494
static PedPartition*
 
495
_rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
 
496
{
 
497
        MacDiskData*            mac_disk_data;
 
498
        PedPartition*           part;
 
499
        MacPartitionData*       mac_part_data;
 
500
        PedSector               block_size;
 
501
        PedSector               start, length;
 
502
 
 
503
        if (!_rawpart_check_signature (raw_part)) {
 
504
#ifndef DISCOVER_ONLY
 
505
                if (ped_exception_throw (
 
506
                        PED_EXCEPTION_WARNING,
 
507
                        PED_EXCEPTION_IGNORE_CANCEL,
 
508
                        _("Partition %d has an invalid signature %x."),
 
509
                        num,
 
510
                        (int) PED_BE16_TO_CPU (raw_part->signature))
 
511
                                != PED_EXCEPTION_IGNORE)
 
512
#endif
 
513
                        goto error;
 
514
        }
 
515
 
 
516
        mac_disk_data = (MacDiskData*) disk->disk_specific;
 
517
        block_size = disk->dev->sector_size / 512;
 
518
 
 
519
        start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
 
520
        length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
 
521
        if (length == 0) {
 
522
#ifndef DISCOVER_ONLY
 
523
                ped_exception_throw (
 
524
                        PED_EXCEPTION_ERROR,
 
525
                        PED_EXCEPTION_CANCEL,
 
526
                        _("Partition %d has an invalid length of 0 bytes!"),
 
527
                        num);
 
528
#endif
 
529
                return NULL;
 
530
        }
 
531
        part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
 
532
                                  start, start + length - 1);
 
533
        if (!part)
 
534
                goto error;
 
535
 
 
536
        mac_part_data = part->disk_specific;
 
537
 
 
538
        strncpy (mac_part_data->volume_name, raw_part->name, 32);
 
539
        strncpy (mac_part_data->system_name, raw_part->type, 32);
 
540
        strncpy (mac_part_data->processor_name, raw_part->processor, 16);
 
541
 
 
542
        mac_part_data->is_boot = _rawpart_is_boot (raw_part);
 
543
        mac_part_data->is_driver = _rawpart_is_driver (raw_part);
 
544
        if (mac_part_data->is_driver)
 
545
                mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
 
546
        mac_part_data->is_root = _rawpart_is_root (raw_part);
 
547
        mac_part_data->is_swap = _rawpart_is_swap (raw_part);
 
548
        mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
 
549
        mac_part_data->is_raid = _rawpart_is_raid (raw_part);
 
550
 
 
551
        /* "data" region */
 
552
#ifndef DISCOVER_ONLY
 
553
        if (raw_part->data_start) {
 
554
                ped_exception_throw (
 
555
                        PED_EXCEPTION_ERROR,
 
556
                        PED_EXCEPTION_CANCEL,
 
557
                        _("The data region doesn't start at the start "
 
558
                          "of the partition."));
 
559
                goto error_destroy_part;
 
560
        }
 
561
#endif /* !DISCOVER_ONLY */
 
562
        mac_part_data->data_region_length
 
563
                = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
 
564
 
 
565
        /* boot region - we have no idea what this is for, but Mac OSX
 
566
         * seems to put garbage here, and doesn't pay any attention to
 
567
         * it afterwards.  [clausen, dan burcaw]
 
568
         */
 
569
#if 0
 
570
        if (raw_part->boot_start) {
 
571
                ped_exception_throw (
 
572
                        PED_EXCEPTION_ERROR,
 
573
                        PED_EXCEPTION_CANCEL,
 
574
                        _("The boot region doesn't start at the start "
 
575
                          "of the partition."));
 
576
                goto error_destroy_part;
 
577
        }
 
578
#endif
 
579
        mac_part_data->boot_region_length
 
580
                = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
 
581
 
 
582
#ifndef DISCOVER_ONLY
 
583
        if (mac_part_data->has_driver) {
 
584
                if (mac_part_data->boot_region_length < part->geom.length) {
 
585
                        if (ped_exception_throw (
 
586
                                PED_EXCEPTION_ERROR,
 
587
                                PED_EXCEPTION_IGNORE_CANCEL,
 
588
                                _("The partition's boot region doesn't occupy "
 
589
                                  "the entire partition."))
 
590
                                        != PED_EXCEPTION_IGNORE)
 
591
                                goto error_destroy_part;
 
592
                }
 
593
        } else {
 
594
                if (mac_part_data->data_region_length < part->geom.length &&
 
595
                    !mac_part_data->is_boot) {
 
596
                        if (ped_exception_throw (
 
597
                                PED_EXCEPTION_ERROR,
 
598
                                PED_EXCEPTION_IGNORE_CANCEL,
 
599
                                _("The partition's data region doesn't occupy "
 
600
                                  "the entire partition."))
 
601
                                        != PED_EXCEPTION_IGNORE)
 
602
                                goto error_destroy_part;
 
603
                }
 
604
        }
 
605
#endif /* !DISCOVER_ONLY */
 
606
 
 
607
        mac_part_data->boot_base_address
 
608
                = PED_BE32_TO_CPU (raw_part->boot_load);
 
609
        mac_part_data->boot_entry_address
 
610
                = PED_BE32_TO_CPU (raw_part->boot_entry);
 
611
        mac_part_data->boot_checksum
 
612
                = PED_BE32_TO_CPU (raw_part->boot_cksum);
 
613
 
 
614
        mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
 
615
        mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
 
616
 
 
617
        return part;
 
618
 
 
619
error_destroy_part:
 
620
        ped_partition_destroy (part);
 
621
error:
 
622
        return NULL;
 
623
}
 
624
 
 
625
/* looks at the partition map size field in a mac raw partition, and calculates
 
626
 * what the size of the partition map should be, from it
 
627
 */
 
628
static int
 
629
_rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
 
630
{
 
631
        MacDiskData*    mac_disk_data = disk->disk_specific;
 
632
        PedSector       sector_size = disk->dev->sector_size / 512;
 
633
        PedSector       part_map_start;
 
634
        PedSector       part_map_end;
 
635
 
 
636
        part_map_start = mac_disk_data->ghost_size;
 
637
        part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
 
638
 
 
639
        return part_map_end - part_map_start + 1;
 
640
}
 
641
 
 
642
static int
 
643
_disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
 
644
{
 
645
        PedSector       block_size;
 
646
 
 
647
        if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
 
648
#ifndef DISCOVER_ONLY
 
649
                ped_exception_throw (
 
650
                        PED_EXCEPTION_ERROR,
 
651
                        PED_EXCEPTION_CANCEL,
 
652
                        _("Weird block size on device descriptor: %d bytes is "
 
653
                          "not divisible by 512."),
 
654
                        (int) PED_BE16_TO_CPU (raw_disk->block_size));
 
655
#endif
 
656
                goto error;
 
657
        }
 
658
 
 
659
        block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
 
660
        if (block_size != disk->dev->sector_size / 512) {
 
661
#ifndef DISCOVER_ONLY
 
662
                if (ped_exception_throw (
 
663
                        PED_EXCEPTION_WARNING,
 
664
                        PED_EXCEPTION_IGNORE_CANCEL,
 
665
                        _("The driver descriptor says the physical block size "
 
666
                          "is %d bytes, but Linux says it is %d bytes."),
 
667
                        (int) block_size * 512,
 
668
                        (int) disk->dev->sector_size)
 
669
                                != PED_EXCEPTION_IGNORE)
 
670
                        goto error;
 
671
#endif
 
672
                disk->dev->sector_size = block_size * 512;
 
673
        }
 
674
 
 
675
        return 1;
 
676
 
 
677
error:
 
678
        return 0;
 
679
}
 
680
 
 
681
/* Tries to figure out the block size used by the drivers, for the ghost
 
682
 * partitioning scheme.  Ghost partitioning works like this: the OpenFirmware
 
683
 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
 
684
 * perhaps, some other number?).  To remain compatible, the partition map
 
685
 * only has "real" partition map entries on ghost-aligned block numbers (and
 
686
 * the others are padded with Apple_Void partitions).  This function tries
 
687
 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
 
688
 * doesn't always equal 2048!!!)
 
689
 */
 
690
static int
 
691
_disk_analyse_ghost_size (PedDisk* disk)
 
692
{
 
693
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
694
 
 
695
        void *buf = ped_malloc (disk->dev->sector_size);
 
696
        if (!buf)
 
697
                return 0;
 
698
 
 
699
        int i;
 
700
        int found = 0;
 
701
        for (i = 1; i < 64; i *= 2) {
 
702
                if (!ped_device_read (disk->dev, buf, i, 1))
 
703
                        break;
 
704
                if (_rawpart_check_signature (buf)
 
705
                    && !_rawpart_is_void (buf)) {
 
706
                        mac_disk_data->ghost_size = i;
 
707
                        found = (i <= disk->dev->sector_size / 512);
 
708
                        break;
 
709
                }
 
710
        }
 
711
        free (buf);
 
712
 
 
713
#ifndef DISCOVER_ONLY
 
714
        if (!found)
 
715
                ped_exception_throw (
 
716
                        PED_EXCEPTION_ERROR,
 
717
                        PED_EXCEPTION_CANCEL,
 
718
                        _("No valid partition map found."));
 
719
#endif
 
720
        return found;
 
721
}
 
722
 
 
723
static int
 
724
mac_read (PedDisk* disk)
 
725
{
 
726
        MacDiskData*            mac_disk_data;
 
727
        PedPartition*           part;
 
728
        int                     num;
 
729
        PedSector               ghost_size;
 
730
        int                     last_part_entry_num = 0;
 
731
 
 
732
        PED_ASSERT (disk != NULL);
 
733
 
 
734
        mac_disk_data = disk->disk_specific;
 
735
        mac_disk_data->part_map_entry_num = 0;          /* 0 == none */
 
736
 
 
737
        void *buf;
 
738
        if (!ptt_read_sector (disk->dev, 0, &buf))
 
739
                return 0;
 
740
 
 
741
        MacRawDisk *raw_disk = (MacRawDisk *) buf;
 
742
 
 
743
        if (!_check_signature (raw_disk))
 
744
                goto error;
 
745
 
 
746
        if (!_disk_analyse_block_size (disk, raw_disk))
 
747
                goto error;
 
748
        if (!_disk_analyse_ghost_size (disk))
 
749
                goto error;
 
750
        ghost_size = mac_disk_data->ghost_size;
 
751
 
 
752
        if (!ped_disk_delete_all (disk))
 
753
                goto error;
 
754
 
 
755
        if (raw_disk->driver_count && raw_disk->driver_count < 62) {
 
756
                memcpy(&mac_disk_data->driverlist[0], &raw_disk->driverlist[0],
 
757
                                sizeof(mac_disk_data->driverlist));
 
758
                mac_disk_data->driver_count = raw_disk->driver_count;
 
759
                mac_disk_data->block_size = raw_disk->block_size;
 
760
        }
 
761
 
 
762
        for (num=1; num==1 || num <= last_part_entry_num; num++) {
 
763
                void *raw_part = buf;
 
764
                if (!ped_device_read (disk->dev, raw_part,
 
765
                                      num * ghost_size, 1))
 
766
                        goto error_delete_all;
 
767
 
 
768
                if (!_rawpart_check_signature (raw_part))
 
769
                        continue;
 
770
 
 
771
                if (num == 1)
 
772
                        last_part_entry_num
 
773
                                = _rawpart_get_partmap_size (raw_part, disk);
 
774
                if (_rawpart_get_partmap_size (raw_part, disk)
 
775
                                != last_part_entry_num) {
 
776
                        if (ped_exception_throw (
 
777
                                PED_EXCEPTION_ERROR,
 
778
                                PED_EXCEPTION_IGNORE_CANCEL,
 
779
                                _("Conflicting partition map entry sizes!  "
 
780
                                  "Entry 1 says it is %d, but entry %d says "
 
781
                                  "it is %d!"),
 
782
                                last_part_entry_num,
 
783
                                _rawpart_get_partmap_size (raw_part, disk))
 
784
                                        != PED_EXCEPTION_IGNORE)
 
785
                                goto error_delete_all;
 
786
                }
 
787
 
 
788
                if (!_rawpart_is_active (raw_part))
 
789
                        continue;
 
790
 
 
791
                part = _rawpart_analyse (raw_part, disk, num);
 
792
                if (!part)
 
793
                        goto error_delete_all;
 
794
                part->num = num;
 
795
                part->fs_type = ped_file_system_probe (&part->geom);
 
796
                PedConstraint *constraint_exact
 
797
                        = ped_constraint_exact (&part->geom);
 
798
                if (constraint_exact == NULL)
 
799
                        goto error_delete_all;
 
800
                bool ok = ped_disk_add_partition (disk, part, constraint_exact);
 
801
                ped_constraint_destroy (constraint_exact);
 
802
                if (!ok)
 
803
                        goto error_delete_all;
 
804
 
 
805
                if (_rawpart_is_partition_map (raw_part)) {
 
806
                        if (mac_disk_data->part_map_entry_num
 
807
                            && ped_exception_throw (
 
808
                                        PED_EXCEPTION_ERROR,
 
809
                                        PED_EXCEPTION_IGNORE_CANCEL,
 
810
                                        _("Weird!  There are 2 partitions "
 
811
                                          "map entries!"))
 
812
                            != PED_EXCEPTION_IGNORE)
 
813
                                goto error_delete_all;
 
814
 
 
815
                        mac_disk_data->part_map_entry_num = num;
 
816
                        mac_disk_data->part_map_entry_count
 
817
                                = part->geom.end - ghost_size + 1;
 
818
                }
 
819
        }
 
820
 
 
821
        if (!mac_disk_data->part_map_entry_num) {
 
822
                if (!_disk_add_part_map_entry (disk, 1))
 
823
                        goto error_delete_all;
 
824
                ped_disk_commit_to_dev (disk);
 
825
        }
 
826
        free (buf);
 
827
        return 1;
 
828
 
 
829
error_delete_all:
 
830
        ped_disk_delete_all (disk);
 
831
error:
 
832
        free (buf);
 
833
        return 0;
 
834
}
 
835
 
 
836
#ifndef DISCOVER_ONLY
 
837
/* The Ghost partition: is a blank entry, used to pad out each block (where
 
838
 * there physical block size > 512 bytes).  This is because OpenFirmware uses
 
839
 * 512 byte blocks, but device drivers Think Different TM, with a different
 
840
 * lbock size, so we need to do this to avoid a clash (!)
 
841
 */
 
842
static int
 
843
_pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
 
844
{
 
845
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
846
        int                     i;
 
847
 
 
848
        size_t ss = disk->dev->sector_size;
 
849
        void *buf = ped_calloc (ss);
 
850
        if (!buf)
 
851
                return 0;
 
852
 
 
853
        MacRawPartition *ghost_entry = buf;
 
854
        ghost_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
 
855
        strcpy (ghost_entry->type, "Apple_Void");
 
856
        ghost_entry->map_count
 
857
                = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
 
858
 
 
859
        for (i=0; i < mac_disk_data->ghost_size - 1; i++) {
 
860
                PedSector idx = i + (num - 1) * mac_disk_data->ghost_size;
 
861
                memcpy ((char*)part_map + idx * ss, ghost_entry, ss);
 
862
        }
 
863
 
 
864
        free (buf);
 
865
        return 1;
 
866
}
 
867
 
 
868
static void
 
869
_update_driver_count (MacRawPartition* part_map_entry,
 
870
                      MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
 
871
{
 
872
        uint16_t        i, count_orig, count_cur, bsz;
 
873
        uint32_t        driver_bs, driver_be, part_be;
 
874
 
 
875
        bsz = mac_disk_data->block_size / 512;
 
876
        count_cur = mac_driverdata->driver_count;
 
877
        count_orig = mac_disk_data->driver_count;
 
878
        for (i = 0; i < count_orig; i++) {
 
879
                driver_bs = mac_disk_data->driverlist[i].block * bsz;
 
880
                driver_be = driver_bs + mac_disk_data->driverlist[i].size;
 
881
                part_be = part_map_entry->start_block + part_map_entry->block_count;
 
882
                if (driver_bs >= part_map_entry->start_block
 
883
                                && driver_be <= part_be) {
 
884
                        mac_driverdata->driverlist[count_cur].block
 
885
                                = mac_disk_data->driverlist[i].block;
 
886
                        mac_driverdata->driverlist[count_cur].size
 
887
                                = mac_disk_data->driverlist[i].size;
 
888
                        mac_driverdata->driverlist[count_cur].type
 
889
                                = mac_disk_data->driverlist[i].type;
 
890
                        mac_driverdata->driver_count++;
 
891
                        break;
 
892
                }
 
893
        }
 
894
}
 
895
 
 
896
static MacRawPartition *
 
897
get_pme (MacRawPartition const *part_map, PedSector i, PedDisk const *disk)
 
898
{
 
899
        MacDiskData const *mac_disk_data = disk->disk_specific;
 
900
        PedSector idx = i * mac_disk_data->ghost_size - 1;
 
901
        return (MacRawPartition *) ((char*)part_map
 
902
                                    + idx * disk->dev->sector_size);
 
903
}
 
904
 
 
905
/* Initialize the disk->dev->sector_size bytes of part_map[part->num]. */
 
906
static int
 
907
_generate_raw_part (PedDisk* disk, PedPartition* part,
 
908
                    MacRawPartition* part_map, MacDiskData *mac_driverdata)
 
909
{
 
910
        MacDiskData*            mac_disk_data;
 
911
        MacPartitionData*       mac_part_data;
 
912
        PedSector               block_size = disk->dev->sector_size / 512;
 
913
 
 
914
        PED_ASSERT (part->num > 0);
 
915
 
 
916
        mac_disk_data = disk->disk_specific;
 
917
        mac_part_data = part->disk_specific;
 
918
 
 
919
        MacRawPartition *part_map_entry = get_pme (part_map, part->num, disk);
 
920
        memset (part_map_entry, 0, disk->dev->sector_size);
 
921
 
 
922
        part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
 
923
        part_map_entry->map_count
 
924
                = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
 
925
        part_map_entry->start_block
 
926
                = PED_CPU_TO_BE32 (part->geom.start / block_size);
 
927
        part_map_entry->block_count
 
928
                = PED_CPU_TO_BE32 (part->geom.length / block_size);
 
929
        strcpy (part_map_entry->name, mac_part_data->volume_name);
 
930
        strcpy (part_map_entry->type, mac_part_data->system_name);
 
931
 
 
932
        if (mac_part_data->is_driver) {
 
933
                mac_part_data->boot_region_length = part->geom.length;
 
934
                if (mac_part_data->has_driver)
 
935
                        _update_driver_count(part_map_entry, mac_driverdata,
 
936
                                        mac_disk_data);
 
937
        } else
 
938
                mac_part_data->data_region_length = part->geom.length;
 
939
        part_map_entry->data_count = PED_CPU_TO_BE32 (
 
940
                        mac_part_data->data_region_length / block_size);
 
941
        part_map_entry->boot_count = PED_CPU_TO_BE32 (
 
942
                        mac_part_data->boot_region_length / block_size);
 
943
        part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
 
944
        part_map_entry->driver_sig
 
945
                = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
 
946
 
 
947
        part_map_entry->boot_load =
 
948
                PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
 
949
        part_map_entry->boot_entry =
 
950
                PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
 
951
        part_map_entry->boot_cksum =
 
952
                PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
 
953
 
 
954
        strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
 
955
 
 
956
        if (!_pad_raw_part (disk, part->num, part_map))
 
957
                goto error;
 
958
 
 
959
        return 1;
 
960
 
 
961
error:
 
962
        return 0;
 
963
}
 
964
 
 
965
static int
 
966
_generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
 
967
                              MacRawPartition* part_map)
 
968
{
 
969
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
970
        PedSector               block_size = disk->dev->sector_size / 512;
 
971
 
 
972
        PED_ASSERT (num > 0);
 
973
 
 
974
        MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
 
975
 
 
976
        part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
 
977
        part_map_entry->map_count
 
978
                = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
 
979
        part_map_entry->start_block
 
980
                = PED_CPU_TO_BE32 (geom->start / block_size);
 
981
        part_map_entry->block_count
 
982
                = PED_CPU_TO_BE32 (geom->length / block_size);
 
983
        strcpy (part_map_entry->name, "Extra");
 
984
        strcpy (part_map_entry->type, "Apple_Free");
 
985
 
 
986
        part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
 
987
        part_map_entry->status = 0;
 
988
        part_map_entry->driver_sig = 0;
 
989
 
 
990
        if (!_pad_raw_part (disk, num, part_map))
 
991
                goto error;
 
992
 
 
993
        return 1;
 
994
 
 
995
error:
 
996
        return 0;
 
997
}
 
998
 
 
999
static int
 
1000
_generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
 
1001
{
 
1002
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
1003
 
 
1004
        PED_ASSERT (num > 0);
 
1005
 
 
1006
        MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
 
1007
        part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
 
1008
        part_map_entry->map_count
 
1009
                = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
 
1010
        strcpy (part_map_entry->type, "Apple_Void");
 
1011
 
 
1012
        return _pad_raw_part (disk, num, part_map);
 
1013
}
 
1014
 
 
1015
/* returns the first empty entry in the partition map */
 
1016
static int _GL_ATTRIBUTE_PURE
 
1017
_get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
 
1018
{
 
1019
        MacDiskData*    mac_disk_data = disk->disk_specific;
 
1020
        int             i;
 
1021
 
 
1022
        for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
 
1023
                MacRawPartition *part_map_entry = get_pme (part_map, i, disk);
 
1024
                if (!part_map_entry->signature)
 
1025
                        return i;
 
1026
        }
 
1027
 
 
1028
        return 0;
 
1029
}
 
1030
 
 
1031
static int
 
1032
write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
 
1033
{
 
1034
        PedDevice*      dev = disk->dev;
 
1035
        void *s0;
 
1036
        if (!ptt_read_sector (dev, 0, &s0))
 
1037
                return 0;
 
1038
        MacRawDisk *raw_disk = (MacRawDisk *) s0;
 
1039
 
 
1040
        raw_disk->signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
 
1041
        raw_disk->block_size = PED_CPU_TO_BE16 (dev->sector_size);
 
1042
        raw_disk->block_count
 
1043
                = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
 
1044
 
 
1045
        raw_disk->driver_count = mac_driverdata->driver_count;
 
1046
        memcpy(&raw_disk->driverlist[0], &mac_driverdata->driverlist[0],
 
1047
                        sizeof(raw_disk->driverlist));
 
1048
 
 
1049
        int write_ok = ped_device_write (dev, raw_disk, 0, 1);
 
1050
        free (s0);
 
1051
        return write_ok;
 
1052
}
 
1053
 
 
1054
static int
 
1055
mac_write (PedDisk* disk)
 
1056
{
 
1057
        MacRawPartition*        part_map;
 
1058
        MacDiskData*            mac_disk_data;
 
1059
        MacDiskData*            mac_driverdata; /* updated driver list */
 
1060
        PedPartition*           part;
 
1061
        int                     num;
 
1062
 
 
1063
        PED_ASSERT (disk != NULL);
 
1064
        PED_ASSERT (disk->disk_specific != NULL);
 
1065
        PED_ASSERT (disk->dev != NULL);
 
1066
        PED_ASSERT (!disk->update_mode);
 
1067
 
 
1068
        mac_disk_data = disk->disk_specific;
 
1069
 
 
1070
        if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
 
1071
                if (!_disk_add_part_map_entry (disk, 1))
 
1072
                        goto error;
 
1073
        }
 
1074
 
 
1075
        mac_driverdata = ped_malloc(sizeof(MacDiskData));
 
1076
        if (!mac_driverdata)
 
1077
                goto error;
 
1078
        memset (mac_driverdata, 0, sizeof(MacDiskData));
 
1079
 
 
1080
        size_t pmap_bytes = (mac_disk_data->part_map_entry_count
 
1081
                             * mac_disk_data->ghost_size
 
1082
                             * disk->dev->sector_size);
 
1083
        part_map = (MacRawPartition*) ped_calloc (pmap_bytes);
 
1084
        if (!part_map)
 
1085
                goto error_free_driverdata;
 
1086
 
 
1087
/* write (to memory) the "real" partitions */
 
1088
        for (part = ped_disk_next_partition (disk, NULL); part;
 
1089
             part = ped_disk_next_partition (disk, part)) {
 
1090
                if (!ped_partition_is_active (part))
 
1091
                        continue;
 
1092
                if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
 
1093
                        goto error_free_part_map;
 
1094
        }
 
1095
 
 
1096
/* write the "free space" partitions */
 
1097
        for (part = ped_disk_next_partition (disk, NULL); part;
 
1098
             part = ped_disk_next_partition (disk, part)) {
 
1099
                if (part->type != PED_PARTITION_FREESPACE)
 
1100
                        continue;
 
1101
                num = _get_first_empty_part_entry (disk, part_map);
 
1102
                if (!_generate_raw_freespace_part (disk, &part->geom, num,
 
1103
                                                   part_map))
 
1104
                        goto error_free_part_map;
 
1105
        }
 
1106
 
 
1107
/* write the "void" (empty) partitions */
 
1108
        for (num = _get_first_empty_part_entry (disk, part_map); num;
 
1109
             num = _get_first_empty_part_entry (disk, part_map))
 
1110
                _generate_empty_part (disk, num, part_map);
 
1111
 
 
1112
/* write to disk */
 
1113
        if (!ped_device_write (disk->dev, part_map, 1,
 
1114
                               mac_disk_data->part_map_entry_count))
 
1115
                goto error_free_part_map;
 
1116
        free (part_map);
 
1117
        int write_ok = write_block_zero (disk, mac_driverdata);
 
1118
        free (mac_driverdata);
 
1119
        return write_ok;
 
1120
 
 
1121
error_free_part_map:
 
1122
        free (part_map);
 
1123
error_free_driverdata:
 
1124
        free (mac_driverdata);
 
1125
error:
 
1126
        return 0;
 
1127
}
 
1128
#endif /* !DISCOVER_ONLY */
 
1129
 
 
1130
static PedPartition*
 
1131
mac_partition_new (
 
1132
        const PedDisk* disk, PedPartitionType part_type,
 
1133
        const PedFileSystemType* fs_type, PedSector start, PedSector end)
 
1134
{
 
1135
        PedPartition*           part;
 
1136
        MacPartitionData*       mac_data;
 
1137
 
 
1138
        part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
 
1139
        if (!part)
 
1140
                goto error;
 
1141
 
 
1142
        if (ped_partition_is_active (part)) {
 
1143
                part->disk_specific
 
1144
                        = mac_data = ped_malloc (sizeof (MacPartitionData));
 
1145
                if (!mac_data)
 
1146
                        goto error_free_part;
 
1147
 
 
1148
                memset (mac_data, 0, sizeof (MacPartitionData));
 
1149
                strcpy (mac_data->volume_name, "untitled");
 
1150
        } else {
 
1151
                part->disk_specific = NULL;
 
1152
        }
 
1153
        return part;
 
1154
 
 
1155
error_free_part:
 
1156
        free (part);
 
1157
error:
 
1158
        return NULL;
 
1159
}
 
1160
 
 
1161
static PedPartition*
 
1162
mac_partition_duplicate (const PedPartition* part)
 
1163
{
 
1164
        PedPartition*           new_part;
 
1165
        MacPartitionData*       new_mac_data;
 
1166
        MacPartitionData*       old_mac_data;
 
1167
 
 
1168
        new_part = ped_partition_new (part->disk, part->type,
 
1169
                                      part->fs_type, part->geom.start,
 
1170
                                      part->geom.end);
 
1171
        if (!new_part)
 
1172
                return NULL;
 
1173
        new_part->num = part->num;
 
1174
 
 
1175
        old_mac_data = (MacPartitionData*) part->disk_specific;
 
1176
        new_mac_data = (MacPartitionData*) new_part->disk_specific;
 
1177
 
 
1178
        /* ugly, but C is ugly :p */
 
1179
        memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
 
1180
        return new_part;
 
1181
}
 
1182
 
 
1183
static void
 
1184
mac_partition_destroy (PedPartition* part)
 
1185
{
 
1186
        PED_ASSERT (part != NULL);
 
1187
 
 
1188
        if (ped_partition_is_active (part))
 
1189
                free (part->disk_specific);
 
1190
        free (part);
 
1191
}
 
1192
 
 
1193
static int
 
1194
mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
 
1195
{
 
1196
        MacPartitionData* mac_data = part->disk_specific;
 
1197
 
 
1198
        part->fs_type = fs_type;
 
1199
 
 
1200
        if (fs_type && is_linux_swap (fs_type->name))
 
1201
                ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
 
1202
 
 
1203
        if (mac_data->is_boot) {
 
1204
                strcpy (mac_data->system_name, "Apple_Bootstrap");
 
1205
                mac_data->status = 0x33;
 
1206
                return 1;
 
1207
        }
 
1208
 
 
1209
        if (fs_type && (!strcmp (fs_type->name, "hfs")
 
1210
                        || !strcmp (fs_type->name, "hfs+"))) {
 
1211
                strcpy (mac_data->system_name, "Apple_HFS");
 
1212
                mac_data->status |= 0x7f;
 
1213
        } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
 
1214
                strcpy (mac_data->system_name, "Apple_HFSX");
 
1215
                mac_data->status |= 0x7f;
 
1216
        } else {
 
1217
                strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
 
1218
                mac_data->status = 0x33;
 
1219
        }
 
1220
 
 
1221
        return 1;
 
1222
}
 
1223
 
 
1224
static int
 
1225
mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
 
1226
{
 
1227
        MacPartitionData*       mac_data;
 
1228
 
 
1229
        PED_ASSERT (part != NULL);
 
1230
        PED_ASSERT (part->disk_specific != NULL);
 
1231
 
 
1232
        mac_data = part->disk_specific;
 
1233
 
 
1234
        switch (flag) {
 
1235
        case PED_PARTITION_BOOT:
 
1236
                mac_data->is_boot = state;
 
1237
 
 
1238
                if (part->fs_type)
 
1239
                        return mac_partition_set_system (part, part->fs_type);
 
1240
 
 
1241
                if (state) {
 
1242
                        strcpy (mac_data->system_name, "Apple_Bootstrap");
 
1243
                        mac_data->status = 0x33;
 
1244
                }
 
1245
                return 1;
 
1246
 
 
1247
        case PED_PARTITION_ROOT:
 
1248
                if (state) {
 
1249
                        strcpy (mac_data->volume_name, "root");
 
1250
                        mac_data->is_swap = 0;
 
1251
                } else {
 
1252
                        if (mac_data->is_root)
 
1253
                                strcpy (mac_data->volume_name, "untitled");
 
1254
                }
 
1255
                mac_data->is_root = state;
 
1256
                return 1;
 
1257
 
 
1258
        case PED_PARTITION_SWAP:
 
1259
                if (state) {
 
1260
                        strcpy (mac_data->volume_name, "swap");
 
1261
                        mac_data->is_root = 0;
 
1262
                } else {
 
1263
                        if (mac_data->is_swap)
 
1264
                                strcpy (mac_data->volume_name, "untitled");
 
1265
                }
 
1266
                mac_data->is_swap = state;
 
1267
                return 1;
 
1268
 
 
1269
        case PED_PARTITION_LVM:
 
1270
                if (state) {
 
1271
                        strcpy (mac_data->system_name, "Linux_LVM");
 
1272
                        mac_data->is_lvm = state;
 
1273
                } else {
 
1274
                        if (mac_data->is_lvm)
 
1275
                                mac_partition_set_system (part, part->fs_type);
 
1276
                }
 
1277
                return 1;
 
1278
 
 
1279
        case PED_PARTITION_RAID:
 
1280
                if (state) {
 
1281
                        strcpy (mac_data->system_name, "Linux_RAID");
 
1282
                        mac_data->is_raid = state;
 
1283
                } else {
 
1284
                        if (mac_data->is_raid)
 
1285
                                mac_partition_set_system (part, part->fs_type);
 
1286
                }
 
1287
                return 1;
 
1288
 
 
1289
        default:
 
1290
                return 0;
 
1291
        }
 
1292
}
 
1293
 
 
1294
static int _GL_ATTRIBUTE_PURE
 
1295
mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
 
1296
{
 
1297
        MacPartitionData*       mac_data;
 
1298
 
 
1299
        PED_ASSERT (part != NULL);
 
1300
        PED_ASSERT (part->disk_specific != NULL);
 
1301
 
 
1302
        mac_data = part->disk_specific;
 
1303
        switch (flag) {
 
1304
        case PED_PARTITION_BOOT:
 
1305
                return mac_data->is_boot;
 
1306
 
 
1307
        case PED_PARTITION_ROOT:
 
1308
                return mac_data->is_root;
 
1309
 
 
1310
        case PED_PARTITION_SWAP:
 
1311
                return mac_data->is_swap;
 
1312
 
 
1313
        case PED_PARTITION_LVM:
 
1314
                return mac_data->is_lvm;
 
1315
 
 
1316
        case PED_PARTITION_RAID:
 
1317
                return mac_data->is_raid;
 
1318
 
 
1319
        default:
 
1320
                return 0;
 
1321
        }
 
1322
}
 
1323
 
 
1324
static int
 
1325
mac_partition_is_flag_available (
 
1326
        const PedPartition* part, PedPartitionFlag flag)
 
1327
{
 
1328
        switch (flag) {
 
1329
        case PED_PARTITION_BOOT:
 
1330
        case PED_PARTITION_ROOT:
 
1331
        case PED_PARTITION_SWAP:
 
1332
        case PED_PARTITION_LVM:
 
1333
        case PED_PARTITION_RAID:
 
1334
                return 1;
 
1335
 
 
1336
        default:
 
1337
                return 0;
 
1338
        }
 
1339
}
 
1340
 
 
1341
static void
 
1342
mac_partition_set_name (PedPartition* part, const char* name)
 
1343
{
 
1344
        MacPartitionData*       mac_data;
 
1345
        int                     i;
 
1346
 
 
1347
        PED_ASSERT (part != NULL);
 
1348
        PED_ASSERT (part->disk_specific != NULL);
 
1349
        mac_data = part->disk_specific;
 
1350
 
 
1351
#ifndef DISCOVER_ONLY
 
1352
        if (mac_data->is_root || mac_data->is_swap) {
 
1353
                if (ped_exception_throw (
 
1354
                        PED_EXCEPTION_WARNING,
 
1355
                        PED_EXCEPTION_IGNORE_CANCEL,
 
1356
                        _("Changing the name of a root or swap partition "
 
1357
                          "will prevent Linux from recognising it as such."))
 
1358
                                != PED_EXCEPTION_IGNORE)
 
1359
                        return;
 
1360
                mac_data->is_root = mac_data->is_swap = 0;
 
1361
        }
 
1362
#endif
 
1363
 
 
1364
        strncpy (mac_data->volume_name, name, 32);
 
1365
        mac_data->volume_name [32] = 0;
 
1366
        for (i = strlen (mac_data->volume_name) - 1;
 
1367
                        mac_data->volume_name[i] == ' '; i--)
 
1368
                mac_data->volume_name [i] = 0;
 
1369
}
 
1370
 
 
1371
static const char* _GL_ATTRIBUTE_PURE
 
1372
mac_partition_get_name (const PedPartition* part)
 
1373
{
 
1374
        MacPartitionData*       mac_data;
 
1375
 
 
1376
        PED_ASSERT (part != NULL);
 
1377
        PED_ASSERT (part->disk_specific != NULL);
 
1378
        mac_data = part->disk_specific;
 
1379
 
 
1380
        return mac_data->volume_name;
 
1381
}
 
1382
 
 
1383
static PedAlignment*
 
1384
mac_get_partition_alignment(const PedDisk *disk)
 
1385
{
 
1386
        PedSector sector_size = disk->dev->sector_size / 512;
 
1387
 
 
1388
        return ped_alignment_new(0, sector_size);
 
1389
}
 
1390
 
 
1391
static PedConstraint*
 
1392
_primary_constraint (PedDisk* disk)
 
1393
{
 
1394
        PedAlignment    start_align;
 
1395
        PedAlignment    end_align;
 
1396
        PedGeometry     max_geom;
 
1397
        PedSector       sector_size;
 
1398
 
 
1399
        sector_size = disk->dev->sector_size / 512;
 
1400
 
 
1401
        if (!ped_alignment_init (&start_align, 0, sector_size))
 
1402
                return NULL;
 
1403
        if (!ped_alignment_init (&end_align, -1, sector_size))
 
1404
                return NULL;
 
1405
        if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
 
1406
                return NULL;
 
1407
 
 
1408
        return ped_constraint_new (&start_align, &end_align, &max_geom,
 
1409
                                   &max_geom, 1, disk->dev->length);
 
1410
}
 
1411
 
 
1412
static int
 
1413
mac_partition_align (PedPartition* part, const PedConstraint* constraint)
 
1414
{
 
1415
        PED_ASSERT (part != NULL);
 
1416
 
 
1417
        if (_ped_partition_attempt_align (part, constraint,
 
1418
                                          _primary_constraint (part->disk)))
 
1419
                return 1;
 
1420
 
 
1421
#ifndef DISCOVER_ONLY
 
1422
        ped_exception_throw (
 
1423
                PED_EXCEPTION_ERROR,
 
1424
                PED_EXCEPTION_CANCEL,
 
1425
                _("Unable to satisfy all constraints on the partition."));
 
1426
#endif
 
1427
        return 0;
 
1428
}
 
1429
 
 
1430
static int
 
1431
mac_partition_enumerate (PedPartition* part)
 
1432
{
 
1433
        PedDisk*                disk;
 
1434
        MacDiskData*            mac_disk_data;
 
1435
        int                     i;
 
1436
        int                     max_part_count;
 
1437
 
 
1438
        PED_ASSERT (part != NULL);
 
1439
        PED_ASSERT (part->disk != NULL);
 
1440
 
 
1441
        disk = part->disk;
 
1442
        mac_disk_data = (MacDiskData*) disk->disk_specific;
 
1443
 
 
1444
        max_part_count = ped_disk_get_max_primary_partition_count (disk);
 
1445
 
 
1446
        if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
 
1447
                return 1;
 
1448
 
 
1449
        for (i = 1; i <= max_part_count; i++) {
 
1450
                if (!ped_disk_get_partition (disk, i)) {
 
1451
                        part->num = i;
 
1452
                        return 1;
 
1453
                }
 
1454
        }
 
1455
 
 
1456
#ifndef DISCOVER_ONLY
 
1457
        ped_exception_throw (
 
1458
                PED_EXCEPTION_ERROR,
 
1459
                PED_EXCEPTION_CANCEL,
 
1460
                _("Can't add another partition -- the partition map is too "
 
1461
                  "small!"));
 
1462
#endif
 
1463
 
 
1464
        return 0;
 
1465
}
 
1466
 
 
1467
static int
 
1468
_disk_count_partitions (PedDisk* disk)
 
1469
{
 
1470
        MacDiskData*            mac_disk_data = disk->disk_specific;
 
1471
        PedPartition*           part = NULL;
 
1472
        PedPartition*           last = NULL;
 
1473
 
 
1474
        PED_ASSERT (disk->update_mode);
 
1475
 
 
1476
        mac_disk_data->active_part_entry_count = 0;
 
1477
        mac_disk_data->free_part_entry_count = 0;
 
1478
        mac_disk_data->last_part_entry_num = 0;
 
1479
 
 
1480
        /* subtle: we only care about free space after the partition map.
 
1481
         * the partition map is an "active" partition, BTW... */
 
1482
        for (part = ped_disk_next_partition (disk, part); part;
 
1483
             part = ped_disk_next_partition (disk, part)) {
 
1484
                if (!ped_partition_is_active (part))
 
1485
                        continue;
 
1486
 
 
1487
                mac_disk_data->active_part_entry_count++;
 
1488
                if (last && last->geom.end + 1 < part->geom.start)
 
1489
                        mac_disk_data->free_part_entry_count++;
 
1490
                mac_disk_data->last_part_entry_num
 
1491
                        = PED_MAX (mac_disk_data->last_part_entry_num,
 
1492
                                   part->num);
 
1493
 
 
1494
                last = part;
 
1495
        }
 
1496
 
 
1497
        if (last && last->geom.end < disk->dev->length - 1)
 
1498
                mac_disk_data->free_part_entry_count++;
 
1499
 
 
1500
        mac_disk_data->last_part_entry_num
 
1501
                = PED_MAX (mac_disk_data->last_part_entry_num,
 
1502
                           mac_disk_data->active_part_entry_count
 
1503
                                + mac_disk_data->free_part_entry_count);
 
1504
        return 1;
 
1505
}
 
1506
 
 
1507
static int
 
1508
add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
 
1509
{
 
1510
        PedPartition*           new_part;
 
1511
        PedConstraint*          constraint_any = ped_constraint_any (disk->dev);
 
1512
 
 
1513
        PED_ASSERT (disk != NULL);
 
1514
 
 
1515
        new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
 
1516
                                      start, end);
 
1517
        if (!new_part)
 
1518
                goto error;
 
1519
        if (!ped_disk_add_partition (disk, new_part, constraint_any))
 
1520
                goto error_destroy_new_part;
 
1521
 
 
1522
        ped_constraint_destroy (constraint_any);
 
1523
        return 1;
 
1524
 
 
1525
error_destroy_new_part:
 
1526
        ped_partition_destroy (new_part);
 
1527
error:
 
1528
        ped_constraint_destroy (constraint_any);
 
1529
        return 0;
 
1530
}
 
1531
 
 
1532
static int
 
1533
mac_alloc_metadata (PedDisk* disk)
 
1534
{
 
1535
        PED_ASSERT (disk != NULL);
 
1536
        PED_ASSERT (disk->disk_specific != NULL);
 
1537
        PED_ASSERT (disk->dev != NULL);
 
1538
 
 
1539
        if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
 
1540
                return 0;
 
1541
 
 
1542
        /* hack: this seems to be a good place, to update the partition map
 
1543
         * entry count, since mac_alloc_metadata() gets called during
 
1544
         * _disk_pop_update_mode()
 
1545
         */
 
1546
        return _disk_count_partitions (disk);
 
1547
}
 
1548
 
 
1549
static int
 
1550
mac_get_max_primary_partition_count (const PedDisk* disk)
 
1551
{
 
1552
        MacDiskData*    mac_disk_data = disk->disk_specific;
 
1553
        PedPartition*   part_map_partition;
 
1554
 
 
1555
        part_map_partition = ped_disk_get_partition (disk,
 
1556
                                        mac_disk_data->part_map_entry_num);
 
1557
 
 
1558
        /* HACK: if we haven't found the partition map partition (yet),
 
1559
         * we return this.
 
1560
         */
 
1561
        if (!part_map_partition) {
 
1562
                mac_disk_data->part_map_entry_num = 0;
 
1563
                return 65536;
 
1564
        }
 
1565
 
 
1566
        /* HACK: since Mac labels need an entry for free-space regions, we
 
1567
         * must allow half plus 1 entries for free-space partitions.  I hate
 
1568
         * this, but things get REALLY complicated, otherwise.
 
1569
         *     (I'm prepared to complicate things later, but I want to get
 
1570
         * everything working, first)
 
1571
         */
 
1572
        return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
 
1573
                - mac_disk_data->free_part_entry_count + 1;
 
1574
}
 
1575
 
 
1576
static bool
 
1577
mac_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
 
1578
{
 
1579
        *max_n = 65536;
 
1580
        return true;
 
1581
}
 
1582
 
 
1583
#include "pt-common.h"
 
1584
PT_define_limit_functions (mac)
 
1585
 
 
1586
static PedDiskOps mac_disk_ops = {
 
1587
        clobber: NULL,
 
1588
        /* FIXME: remove this cast, once mac_write is fixed not to
 
1589
           modify its *DISK parameter.  */
 
1590
        write:  NULL_IF_DISCOVER_ONLY ((int (*) (const PedDisk*)) mac_write),
 
1591
 
 
1592
        partition_set_name:     mac_partition_set_name,
 
1593
        partition_get_name:     mac_partition_get_name,
 
1594
 
 
1595
        get_partition_alignment: mac_get_partition_alignment,
 
1596
 
 
1597
        PT_op_function_initializers (mac)
 
1598
};
 
1599
 
 
1600
static PedDiskType mac_disk_type = {
 
1601
        next:           NULL,
 
1602
        name:           "mac",
 
1603
        ops:            &mac_disk_ops,
 
1604
        features:       PED_DISK_TYPE_PARTITION_NAME
 
1605
};
 
1606
 
 
1607
void
 
1608
ped_disk_mac_init ()
 
1609
{
 
1610
        PED_ASSERT (sizeof (MacRawPartition) == 512);
 
1611
        PED_ASSERT (sizeof (MacRawDisk) == 512);
 
1612
 
 
1613
        ped_disk_type_register (&mac_disk_type);
 
1614
}
 
1615
 
 
1616
void
 
1617
ped_disk_mac_done ()
 
1618
{
 
1619
        ped_disk_type_unregister (&mac_disk_type);
 
1620
}