OSDN Git Service

maint: update most copyright year lists to include 2009
[android-x86/external-parted.git] / libparted / labels / dasd.c
1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
3     libparted - a library for manipulating disk partitions
4     Copyright (C) 2000-2001, 2007-2009 Free Software Foundation, Inc.
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19     Contributor:  Phil Knirsch <phil@redhat.de>
20                   Harald Hoyer <harald@redhat.de>
21 */
22
23 #include <config.h>
24
25 #include <stdio.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <stdbool.h>
32
33 #include <sys/stat.h>
34 #include <sys/ioctl.h>
35 #include <parted/parted.h>
36 #include <parted/endian.h>
37 #include <parted/debug.h>
38
39 #include <parted/vtoc.h>
40 #include <parted/fdasd.h>
41 #include <arch/linux.h>
42
43 #include <libintl.h>
44 #if ENABLE_NLS
45 #  define _(String) dgettext (PACKAGE, String)
46 #else
47 #  define _(String) (String)
48 #endif /* ENABLE_NLS */
49
50 #include "misc.h"
51
52 #define PARTITION_LINUX_SWAP 0x82
53 #define PARTITION_LINUX 0x83
54 #define PARTITION_LINUX_EXT 0x85
55 #define PARTITION_LINUX_LVM 0x8e
56 #define PARTITION_LINUX_RAID 0xfd
57 #define PARTITION_LINUX_LVM_OLD 0xfe
58
59 extern void ped_disk_dasd_init ();
60 extern void ped_disk_dasd_done ();
61
62 #define DASD_NAME "dasd"
63
64 typedef struct {
65         int type;
66         int system;
67         int     raid;
68         int     lvm;
69         void *part_info;
70 } DasdPartitionData;
71
72 typedef struct {
73         unsigned int real_sector_size;
74         unsigned int format_type;
75         /* IBM internal dasd structure (i guess ;), required. */
76         struct fdasd_anchor *anchor;
77 } DasdDiskSpecific;
78
79 static int dasd_probe (const PedDevice *dev);
80 static int dasd_clobber (PedDevice* dev);
81 static int dasd_read (PedDisk* disk);
82 static int dasd_write (const PedDisk* disk);
83
84 static PedPartition* dasd_partition_new (const PedDisk* disk,
85                                                                                  PedPartitionType part_type,
86                                                                                  const PedFileSystemType* fs_type,
87                                                                                  PedSector start,
88                                                                                  PedSector end);
89 static void dasd_partition_destroy (PedPartition* part);
90 static int dasd_partition_set_flag (PedPartition* part,
91                                                                         PedPartitionFlag flag,
92                                                                         int state);
93 static int dasd_partition_get_flag (const PedPartition* part,
94                                                                         PedPartitionFlag flag);
95 static int dasd_partition_is_flag_available (const PedPartition* part,
96                                                                                          PedPartitionFlag flag);
97 static int dasd_partition_align (PedPartition* part,
98                                                                  const PedConstraint* constraint);
99 static int dasd_partition_enumerate (PedPartition* part);
100 static int dasd_get_max_primary_partition_count (const PedDisk* disk);
101 static bool dasd_get_max_supported_partition_count (const PedDisk* disk, int *max_n);
102
103 static PedDisk* dasd_alloc (const PedDevice* dev);
104 static PedDisk* dasd_duplicate (const PedDisk* disk);
105 static void dasd_free (PedDisk* disk);
106 static int dasd_partition_set_system (PedPartition* part,
107                                                                           const PedFileSystemType* fs_type);
108 static int dasd_alloc_metadata (PedDisk* disk);
109
110 static PedDiskOps dasd_disk_ops = {
111         probe: dasd_probe,
112         clobber: dasd_clobber,
113         read: dasd_read,
114         write: dasd_write,
115
116         alloc: dasd_alloc,
117         duplicate: dasd_duplicate,
118         free: dasd_free,
119         partition_set_system: dasd_partition_set_system,
120
121         partition_new: dasd_partition_new,
122         partition_destroy: dasd_partition_destroy,
123         partition_set_flag:     dasd_partition_set_flag,
124         partition_get_flag:     dasd_partition_get_flag,
125         partition_is_flag_available: dasd_partition_is_flag_available,
126         partition_set_name:     NULL,
127         partition_get_name:     NULL,
128         partition_align: dasd_partition_align,
129         partition_enumerate: dasd_partition_enumerate,
130
131         alloc_metadata: dasd_alloc_metadata,
132         get_max_primary_partition_count: dasd_get_max_primary_partition_count,
133         get_max_supported_partition_count: dasd_get_max_supported_partition_count,
134
135         partition_duplicate: NULL
136 };
137
138 static PedDiskType dasd_disk_type = {
139         next: NULL,
140         name: "dasd",
141         ops: &dasd_disk_ops,
142         features: 0
143 };
144
145 static PedDisk*
146 dasd_alloc (const PedDevice* dev)
147 {
148         PedDisk* disk;
149         LinuxSpecific* arch_specific;
150         DasdDiskSpecific *disk_specific;
151
152         PED_ASSERT (dev != NULL, return NULL);
153
154         arch_specific = LINUX_SPECIFIC (dev);
155         disk = _ped_disk_alloc (dev, &dasd_disk_type);
156         if (!disk)
157                 return NULL;
158
159         disk->disk_specific = disk_specific = ped_malloc(sizeof(DasdDiskSpecific));
160         if (!disk->disk_specific) {
161                 free (disk);
162                 return NULL;
163         }
164
165         /* because we lie to parted we have to compensate with the
166            real sector size.  Record that now. */
167         if (ioctl(arch_specific->fd, BLKSSZGET,
168                           &disk_specific->real_sector_size) == -1) {
169                 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
170                                                         _("Unable to determine the block "
171                                                           "size of this dasd"));
172                 free(disk_specific);
173                 free(disk);
174                 return NULL;
175         }
176
177         return disk;
178 }
179
180 static PedDisk*
181 dasd_duplicate (const PedDisk* disk)
182 {
183         PedDisk* new_disk;
184
185         new_disk = ped_disk_new_fresh(disk->dev, &dasd_disk_type);
186
187         if (!new_disk)
188                 return NULL;
189
190         new_disk->disk_specific = NULL;
191
192         return new_disk;
193 }
194
195 static void
196 dasd_free (PedDisk* disk)
197 {
198         PED_ASSERT(disk != NULL, return);
199
200         _ped_disk_free(disk);
201 }
202
203
204 void
205 ped_disk_dasd_init ()
206 {
207         ped_disk_type_register(&dasd_disk_type);
208 }
209
210 void
211 ped_disk_dasd_done ()
212 {
213         ped_disk_type_unregister(&dasd_disk_type);
214 }
215
216 static int
217 dasd_probe (const PedDevice *dev)
218 {
219         LinuxSpecific* arch_specific;
220         struct fdasd_anchor anchor;
221
222         PED_ASSERT(dev != NULL, return 0);
223
224         if (!(dev->type == PED_DEVICE_DASD || dev->type == PED_DEVICE_VIODASD))
225                 return 0;
226
227         arch_specific = LINUX_SPECIFIC(dev);
228
229         /* add partition test here */
230         fdasd_initialize_anchor(&anchor);
231
232         fdasd_get_geometry(&anchor, arch_specific->fd);
233
234         fdasd_check_api_version(&anchor, arch_specific->fd);
235
236         if (fdasd_check_volume(&anchor, arch_specific->fd))
237                 goto error_cleanup;
238
239         fdasd_cleanup(&anchor);
240
241         return 1;
242
243  error_cleanup:
244         fdasd_cleanup(&anchor);
245         ped_exception_throw(PED_EXCEPTION_ERROR,PED_EXCEPTION_IGNORE_CANCEL,
246                             "Error while probing device %s.", dev->path);
247
248         return 0;
249 }
250
251 static int
252 dasd_clobber (PedDevice* dev)
253 {
254         LinuxSpecific* arch_specific;
255         struct fdasd_anchor anchor;
256
257         PED_ASSERT(dev != NULL, return 0);
258
259         arch_specific = LINUX_SPECIFIC(dev);
260
261         fdasd_initialize_anchor(&anchor);
262         fdasd_get_geometry(&anchor, arch_specific->fd);
263
264         fdasd_recreate_vtoc(&anchor);
265         fdasd_write_labels(&anchor, arch_specific->fd);
266
267         return 1;
268 }
269
270 static int
271 dasd_read (PedDisk* disk)
272 {
273         int i;
274         char str[20];
275         PedDevice* dev;
276         PedPartition* part;
277         PedFileSystemType *fs;
278         PedSector start, end;
279         PedConstraint* constraint_exact;
280         partition_info_t *p;
281         LinuxSpecific* arch_specific;
282         DasdDiskSpecific* disk_specific;
283
284         PDEBUG;
285
286         PED_ASSERT (disk != NULL, return 0);
287         PDEBUG;
288         PED_ASSERT (disk->dev != NULL, return 0);
289         PDEBUG;
290
291         dev = disk->dev;
292
293         arch_specific = LINUX_SPECIFIC(dev);
294         disk_specific = disk->disk_specific;
295
296         disk_specific->anchor = ped_malloc(sizeof(fdasd_anchor_t));
297
298         PDEBUG;
299
300         fdasd_initialize_anchor(disk_specific->anchor);
301
302         fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
303
304         /* check dasd for labels and vtoc */
305         if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
306                 goto error_close_dev;
307
308         if ((disk_specific->anchor->geo.cylinders
309                 * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
310                 disk_specific->anchor->big_disk++;
311
312         ped_disk_delete_all (disk);
313
314         if (strncmp(disk_specific->anchor->vlabel->volkey,
315                                 vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0) {
316                 DasdPartitionData* dasd_data;
317
318                 /* LDL format, old one */
319                 disk_specific->format_type = 1;
320                 start = 24;
321                 end = (long long)(long long) disk_specific->anchor->geo.cylinders
322                       * (long long)disk_specific->anchor->geo.heads
323                       * (long long)disk->dev->hw_geom.sectors
324                       * (long long)disk_specific->real_sector_size
325                       / (long long)disk->dev->sector_size - 1;
326                 part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end);
327                 if (!part)
328                         goto error_close_dev;
329
330                 part->num = 1;
331                 part->fs_type = ped_file_system_probe (&part->geom);
332                 dasd_data = part->disk_specific;
333                 dasd_data->raid = 0;
334                 dasd_data->lvm = 0;
335                 dasd_data->type = 0;
336
337                 if (!ped_disk_add_partition (disk, part, NULL))
338                         goto error_close_dev;
339
340                 return 1;
341         }
342
343         /* CDL format, newer */
344         disk_specific->format_type = 2;
345
346         p = disk_specific->anchor->first;
347         PDEBUG;
348
349         for (i = 1 ; i <= USABLE_PARTITIONS; i++) {
350                 char *ch = p->f1->DS1DSNAM;
351                 DasdPartitionData* dasd_data;
352
353
354                 if (p->used != 0x01)
355                         continue;
356
357         PDEBUG;
358
359                 start = (long long)(long long) p->start_trk
360                                 * (long long) disk->dev->hw_geom.sectors
361                                 * (long long) disk_specific->real_sector_size
362                                 / (long long) disk->dev->sector_size;
363                 end   = (long long)((long long) p->end_trk + 1)
364                                 * (long long) disk->dev->hw_geom.sectors
365                                 * (long long) disk_specific->real_sector_size
366                                 / (long long) disk->dev->sector_size - 1;
367                 part = ped_partition_new(disk, PED_PARTITION_NORMAL, NULL,
368                                          start, end);
369         PDEBUG;
370
371                 if (!part)
372                         goto error_close_dev;
373
374         PDEBUG;
375
376                 part->num = i;
377                 part->fs_type = ped_file_system_probe(&part->geom);
378
379                 vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
380                 ch = strstr(p->f1->DS1DSNAM, "PART");
381
382                 if (ch != NULL) {
383                         strncpy(str, ch+9, 6);
384                         str[6] = '\0';
385                 }
386
387                 dasd_data = part->disk_specific;
388
389                 if ((strncmp(PART_TYPE_RAID, str, 6) == 0) &&
390                     (ped_file_system_probe(&part->geom) == NULL))
391                         ped_partition_set_flag(part, PED_PARTITION_RAID, 1);
392                 else
393                         ped_partition_set_flag(part, PED_PARTITION_RAID, 0);
394
395                 if ((strncmp(PART_TYPE_LVM, str, 6) == 0) &&
396                     (ped_file_system_probe(&part->geom) == NULL))
397                         ped_partition_set_flag(part, PED_PARTITION_LVM, 1);
398                 else
399                         ped_partition_set_flag(part, PED_PARTITION_LVM, 0);
400
401                 if (strncmp(PART_TYPE_SWAP, str, 6) == 0) {
402                         fs = ped_file_system_probe(&part->geom);
403                         if (is_linux_swap(fs->name)) {
404                                 dasd_data->system = PARTITION_LINUX_SWAP;
405                                 PDEBUG;
406                         }
407                 }
408
409                 vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
410
411                 dasd_data->part_info = (void *) p;
412                 dasd_data->type = 0;
413
414                 constraint_exact = ped_constraint_exact (&part->geom);
415                 if (!constraint_exact)
416                         goto error_close_dev;
417                 if (!ped_disk_add_partition(disk, part, constraint_exact))
418                         goto error_close_dev;
419                 ped_constraint_destroy(constraint_exact);
420
421                 if (p->fspace_trk > 0) {
422                         start = (long long)((long long) p->end_trk + 1)
423                                         * (long long) disk->dev->hw_geom.sectors
424                                         * (long long) disk_specific->real_sector_size
425                                         / (long long) disk->dev->sector_size;
426                         end   = (long long)((long long) p->end_trk + 1 + p->fspace_trk)
427                                         * (long long) disk->dev->hw_geom.sectors
428                                         * (long long) disk_specific->real_sector_size
429                                         / (long long) disk->dev->sector_size - 1;
430                         part = ped_partition_new (disk, PED_PARTITION_NORMAL,
431                                                   NULL, start, end);
432
433                         if (!part)
434                                 goto error_close_dev;
435
436                         part->type = PED_PARTITION_FREESPACE;
437                         constraint_exact = ped_constraint_exact(&part->geom);
438
439                         if (!constraint_exact)
440                                 goto error_close_dev;
441                         if (!ped_disk_add_partition(disk, part, constraint_exact))
442                                 goto error_close_dev;
443
444                         ped_constraint_destroy (constraint_exact);
445                 }
446
447                 p = p->next;
448         }
449
450         PDEBUG;
451         return 1;
452
453 error_close_dev:
454         PDEBUG;
455         return 0;
456 }
457
458 static int
459 dasd_update_type (const PedDisk* disk)
460 {
461         PedPartition* part;
462         LinuxSpecific* arch_specific;
463         DasdDiskSpecific* disk_specific;
464
465         arch_specific = LINUX_SPECIFIC(disk->dev);
466         disk_specific = disk->disk_specific;
467
468         PDEBUG;
469
470         for (part = ped_disk_next_partition(disk, NULL); part;
471              part = ped_disk_next_partition(disk, part)) {
472                 partition_info_t *p;
473                 char *ch = NULL;
474                 DasdPartitionData* dasd_data;
475
476                 PDEBUG;
477
478                 if (part->type & PED_PARTITION_FREESPACE
479                         || part->type & PED_PARTITION_METADATA)
480                         continue;
481
482                 PDEBUG;
483
484                 dasd_data = part->disk_specific;
485                 p = dasd_data->part_info;
486
487                 if (!p ) {
488                         PDEBUG;
489                         continue;
490                 }
491
492                 vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
493                 ch = strstr(p->f1->DS1DSNAM, "PART");
494
495                 PDEBUG;
496                 if (ch == NULL) {
497                         vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
498                         PDEBUG;
499                         continue;
500                 }
501
502                 ch += 9;
503
504                 switch (dasd_data->system) {
505                         case PARTITION_LINUX_LVM:
506                                 PDEBUG;
507                                 strncpy(ch, PART_TYPE_LVM, 6);
508                                 break;
509                         case PARTITION_LINUX_RAID:
510                                 PDEBUG;
511                                 strncpy(ch, PART_TYPE_RAID, 6);
512                                 break;
513                         case PARTITION_LINUX:
514                                 PDEBUG;
515                                 strncpy(ch, PART_TYPE_NATIVE, 6);
516                                 break;
517                         case PARTITION_LINUX_SWAP:
518                                 PDEBUG;
519                                 strncpy(ch, PART_TYPE_SWAP, 6);
520                                 break;
521                         default:
522                                 PDEBUG;
523                                 strncpy(ch, PART_TYPE_NATIVE, 6);
524                                 break;
525                 }
526
527                 disk_specific->anchor->vtoc_changed++;
528                 vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
529         }
530
531         return 1;
532 }
533
534 static int
535 dasd_write (const PedDisk* disk)
536 {
537         DasdPartitionData* dasd_data;
538         PedPartition* part;
539         int i;
540         partition_info_t *p;
541         LinuxSpecific* arch_specific;
542         DasdDiskSpecific* disk_specific;
543         PED_ASSERT(disk != NULL, return 0);
544         PED_ASSERT(disk->dev != NULL, return 0);
545
546         arch_specific = LINUX_SPECIFIC (disk->dev);
547         disk_specific = disk->disk_specific;
548
549         PDEBUG;
550
551         /* If formated in LDL, don't write anything. */
552         if (disk_specific->format_type == 1)
553                 return 1;
554
555         /* XXX re-initialize anchor? */
556         fdasd_initialize_anchor(disk_specific->anchor);
557         fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
558
559         /* check dasd for labels and vtoc */
560         if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
561                 goto error;
562
563         if ((disk_specific->anchor->geo.cylinders
564                 * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
565                 disk_specific->anchor->big_disk++;
566
567         fdasd_recreate_vtoc(disk_specific->anchor);
568
569         for (i = 1; i <= USABLE_PARTITIONS; i++) {
570                 unsigned int start, stop;
571                 int type;
572
573                 PDEBUG;
574                 part = ped_disk_get_partition(disk, i);
575                 if (!part)
576                         continue;
577
578                 PDEBUG;
579
580                 start = part->geom.start * disk->dev->sector_size
581                                 / disk_specific->real_sector_size / disk->dev->hw_geom.sectors;
582                 stop = (part->geom.end + 1)
583                            * disk->dev->sector_size / disk_specific->real_sector_size
584                            / disk->dev->hw_geom.sectors - 1;
585
586                 PDEBUG;
587                 dasd_data = part->disk_specific;
588
589                 type = dasd_data->type;
590                 PDEBUG;
591
592                 p = fdasd_add_partition(disk_specific->anchor, start, stop);
593                 if (!p) {
594                         PDEBUG;
595                         return 0;
596                 }
597                 dasd_data->part_info = (void *) p;
598                 p->type = dasd_data->system;
599         }
600
601         PDEBUG;
602
603         if (!fdasd_prepare_labels(disk_specific->anchor, arch_specific->fd))
604                 return 0;
605
606         dasd_update_type(disk);
607         PDEBUG;
608
609         if (!fdasd_write_labels(disk_specific->anchor, arch_specific->fd))
610                 return 0;
611
612         return 1;
613
614 error:
615         PDEBUG;
616         return 0;
617 }
618
619 static PedPartition*
620 dasd_partition_new (const PedDisk* disk, PedPartitionType part_type,
621                     const PedFileSystemType* fs_type,
622                     PedSector start, PedSector end)
623 {
624         PedPartition* part;
625
626         part = _ped_partition_alloc(disk, part_type, fs_type, start, end);
627         if (!part)
628                 goto error;
629
630         part->disk_specific = ped_malloc (sizeof (DasdPartitionData));
631         return part;
632
633 error:
634         return 0;
635 }
636
637 static void
638 dasd_partition_destroy (PedPartition* part)
639 {
640         PED_ASSERT(part != NULL, return);
641
642         if (ped_partition_is_active(part))
643                 free(part->disk_specific);
644         free(part);
645 }
646
647 static int
648 dasd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
649 {
650         DasdPartitionData* dasd_data;
651
652         PED_ASSERT(part != NULL, return 0);
653         PED_ASSERT(part->disk_specific != NULL, return 0);
654         dasd_data = part->disk_specific;
655
656         switch (flag) {
657                 case PED_PARTITION_RAID:
658                         if (state)
659                                 dasd_data->lvm = 0;
660                         dasd_data->raid = state;
661                         return ped_partition_set_system(part, part->fs_type);
662                 case PED_PARTITION_LVM:
663                         if (state)
664                                 dasd_data->raid = 0;
665                         dasd_data->lvm = state;
666                         return ped_partition_set_system(part, part->fs_type);
667                 default:
668                         return 0;
669         }
670 }
671
672 static int
673 dasd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
674 {
675         DasdPartitionData* dasd_data;
676
677         PED_ASSERT (part != NULL, return 0);
678         PED_ASSERT (part->disk_specific != NULL, return 0);
679         dasd_data = part->disk_specific;
680
681         switch (flag) {
682                 case PED_PARTITION_RAID:
683                         return dasd_data->raid;
684                 case PED_PARTITION_LVM:
685                         return dasd_data->lvm;
686                 default:
687                         return 0;
688         }
689 }
690
691 static int
692 dasd_partition_is_flag_available (const PedPartition* part,
693                                   PedPartitionFlag flag)
694 {
695         switch (flag) {
696                 case PED_PARTITION_RAID:
697                         return 1;
698                 case PED_PARTITION_LVM:
699                         return 1;
700                 default:
701                         return 0;
702         }
703 }
704
705
706 static int
707 dasd_get_max_primary_partition_count (const PedDisk* disk)
708 {
709         DasdDiskSpecific* disk_specific;
710
711         disk_specific = disk->disk_specific;
712         /* If formated in LDL, maximum partition number is 1 */
713         if (disk_specific->format_type == 1)
714                 return 1;
715
716         return USABLE_PARTITIONS;
717 }
718
719 static bool
720 dasd_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
721 {
722         *max_n = dasd_get_max_primary_partition_count(disk);
723         return true;
724 }
725
726 static PedConstraint*
727 _primary_constraint (PedDisk* disk)
728 {
729         PedAlignment start_align;
730         PedAlignment end_align;
731         PedGeometry     max_geom;
732         PedSector sector_size;
733         LinuxSpecific* arch_specific;
734         DasdDiskSpecific* disk_specific;
735
736         PDEBUG;
737
738         arch_specific = LINUX_SPECIFIC (disk->dev);
739         disk_specific = disk->disk_specific;
740         sector_size = disk_specific->real_sector_size / disk->dev->sector_size;
741
742         if (!ped_alignment_init (&start_align, 0,
743                                                          disk->dev->hw_geom.sectors * sector_size))
744                 return NULL;
745         if (!ped_alignment_init (&end_align, -1,
746                                                      disk->dev->hw_geom.sectors * sector_size))
747                 return NULL;
748         if (!ped_geometry_init (&max_geom, disk->dev, 0, disk->dev->length))
749                 return NULL;
750
751         return ped_constraint_new(&start_align, &end_align, &max_geom,
752                                                           &max_geom, 1, disk->dev->length);
753 }
754
755 static int
756 dasd_partition_align (PedPartition* part, const PedConstraint* constraint)
757 {
758         DasdDiskSpecific* disk_specific;
759
760         PED_ASSERT (part != NULL, return 0);
761
762         disk_specific = part->disk->disk_specific;
763         /* If formated in LDL, ignore metadata partition */
764         if (disk_specific->format_type == 1)
765                 return 1;
766
767         if (_ped_partition_attempt_align(part, constraint,
768                                                                      _primary_constraint(part->disk)))
769                 return 1;
770
771 #ifndef DISCOVER_ONLY
772         ped_exception_throw (
773                 PED_EXCEPTION_ERROR,
774                 PED_EXCEPTION_CANCEL,
775                 _("Unable to satisfy all constraints on the partition."));
776 #endif
777
778         return 0;
779 }
780
781 static int
782 dasd_partition_enumerate (PedPartition* part)
783 {
784         int i;
785         PedPartition* p;
786
787         /* never change the partition numbers */
788         if (part->num != -1)
789                 return 1;
790
791         for (i = 1; i <= USABLE_PARTITIONS; i++) {
792                 p = ped_disk_get_partition (part->disk, i);
793                 if (!p) {
794                         part->num = i;
795                         return 1;
796                 }
797         }
798
799         /* failed to allocate a number */
800         ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
801                                                 _("Unable to allocate a dasd disklabel slot"));
802         return 0;
803 }
804
805 static int
806 dasd_partition_set_system (PedPartition* part,
807                            const PedFileSystemType* fs_type)
808 {
809         DasdPartitionData* dasd_data = part->disk_specific;
810         PedSector cyl_size;
811
812         cyl_size=part->disk->dev->hw_geom.sectors * part->disk->dev->hw_geom.heads;
813         PDEBUG;
814
815         part->fs_type = fs_type;
816
817         if (dasd_data->lvm) {
818                 dasd_data->system = PARTITION_LINUX_LVM;
819         PDEBUG;
820                 return 1;
821         }
822
823         if (dasd_data->raid) {
824                 dasd_data->system = PARTITION_LINUX_RAID;
825         PDEBUG;
826                 return 1;
827         }
828
829         if (!fs_type) {
830                 dasd_data->system = PARTITION_LINUX;
831         PDEBUG;
832         } else if (is_linux_swap (fs_type->name)) {
833                 dasd_data->system = PARTITION_LINUX_SWAP;
834         PDEBUG;
835         } else {
836                 dasd_data->system = PARTITION_LINUX;
837         PDEBUG;
838         }
839
840         return 1;
841 }
842
843 static int
844 dasd_alloc_metadata (PedDisk* disk)
845 {
846         PedPartition* new_part;
847         PedConstraint* constraint_any = NULL;
848         PedSector vtoc_end;
849         LinuxSpecific* arch_specific;
850         DasdDiskSpecific* disk_specific;
851
852         PED_ASSERT (disk != NULL, goto error);
853         PED_ASSERT (disk->dev != NULL, goto error);
854
855         arch_specific = LINUX_SPECIFIC (disk->dev);
856         disk_specific = disk->disk_specific;
857
858         constraint_any = ped_constraint_any (disk->dev);
859
860         /* If formated in LDL, the real partition starts at sector 24. */
861         if (disk_specific->format_type == 1)
862                 vtoc_end = 23;
863         else
864         /* Mark the start of the disk as metadata. */
865                 vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors
866                                    * (long long) disk_specific->real_sector_size
867                                    / (long long) disk->dev->sector_size) - 1;
868
869         new_part = ped_partition_new (disk,PED_PARTITION_METADATA,NULL,0,vtoc_end);
870         if (!new_part)
871                 goto error;
872
873         if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
874                 ped_partition_destroy (new_part);
875                 goto error;
876         }
877
878         ped_constraint_destroy (constraint_any);
879         return 1;
880
881 error:
882         ped_constraint_destroy (constraint_any);
883         return 0;
884 }