]> git.pld-linux.org Git - packages/parted.git/commitdiff
- updated for 1.7.1 from FC, adjusted two prototypes to kill warnings
authorJakub Bogusz <qboosh@pld-linux.org>
Sat, 27 May 2006 22:08:02 +0000 (22:08 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    parted-aix.patch -> 1.3
    parted-dasd.patch -> 1.4

parted-aix.patch
parted-dasd.patch

index 142620442baa0f4c2f95be1619e4e0c77c2847c1..f5a83e83de73a1d180a112215aa159672434fb00 100644 (file)
@@ -1,6 +1,69 @@
---- parted-1.6.3/libparted/disk_aix.c.aix      2003-05-28 02:37:39.000000000 -0400
-+++ parted-1.6.3/libparted/disk_aix.c  2003-05-28 02:54:28.000000000 -0400
-@@ -0,0 +1,283 @@
+--- parted-1.7.0/libparted/libparted.c.P151    2006-05-19 10:45:10.000000000 -0400
++++ parted-1.7.0/libparted/libparted.c 2006-05-19 11:45:51.000000000 -0400
+@@ -80,6 +80,7 @@
+       return 1;
+ }
++extern void ped_disk_aix_init ();
+ extern void ped_disk_bsd_init ();
+ extern void ped_disk_dvh_init ();
+ extern void ped_disk_gpt_init ();
+@@ -110,7 +111,7 @@
+       ped_disk_dvh_init ();
+       ped_disk_bsd_init ();
+       ped_disk_amiga_init ();
+-
++      ped_disk_aix_init ();
+ }
+ #ifdef ENABLE_FS
+@@ -141,6 +142,7 @@
+ }
+ #endif /* ENABLE_FS */
++extern void ped_disk_aix_done ();
+ extern void ped_disk_bsd_done ();
+ extern void ped_disk_dvh_done ();
+ extern void ped_disk_gpt_done ();
+@@ -169,6 +171,7 @@
+       ped_disk_dvh_done ();
+       ped_disk_bsd_done ();
+       ped_disk_amiga_done ();
++      ped_disk_aix_done ();
+ }
+ static void _init() __attribute__ ((constructor));
+--- parted-1.7.0/libparted/labels/Makefile.am.P151     2006-05-19 10:40:22.000000000 -0400
++++ parted-1.7.0/libparted/labels/Makefile.am  2006-05-19 11:42:26.000000000 -0400
+@@ -25,7 +25,8 @@
+                       loop.c          \
+                       mac.c           \
+                       pc98.c          \
+-                      sun.c
++                      sun.c                   \
++                      aix.c
+                       
+ liblabels_la_LIBADD   = @OS_LIBS@
+--- parted-1.7.0/libparted/labels/dos.c.P151   2006-05-15 05:19:34.000000000 -0400
++++ parted-1.7.0/libparted/labels/dos.c        2006-05-19 11:44:40.000000000 -0400
+@@ -185,6 +185,13 @@
+                       return 0;
+       }
++      /* If this is an AIX Physical Volume, fail here.  IBMA in EBCDIC */
++      if (part_table.boot_code[0] == (char) 0xc9 && 
++          part_table.boot_code[1] == (char) 0xc2 &&
++          part_table.boot_code[2] == (char) 0xd4 && 
++          part_table.boot_code[3] == (char) 0xc1)
++              return 0;
++
+ #ifdef ENABLE_PC98
+       /* HACK: it's impossible to tell PC98 and msdos disk labels apart.
+        * Someone made the signatures the same (very clever).  Since
+--- parted-1.7.0/libparted/labels/aix.c.P151   2006-05-19 11:43:15.000000000 -0400
++++ parted-1.7.0/libparted/labels/aix.c        2006-05-19 11:42:59.000000000 -0400
+@@ -0,0 +1,282 @@
 +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 +
 +    libparted - a library for manipulating disk partitions
 +static PedDiskType aix_disk_type;
 +
 +static int
-+aix_probe (PedDevice *dev)
++aix_probe (const PedDevice *dev)
 +{
 +      PedDiskType*    disk_type;
 +      AixLabel        label;
 +#endif /* !DISCOVER_ONLY */
 +
 +static PedDisk*
-+aix_alloc (PedDevice* dev)
++aix_alloc (const PedDevice* dev)
 +{
 +      PedDisk*        disk;
 +
 +{
 +      ped_unregister_disk_type (&aix_disk_type);
 +}
-+
---- parted-1.6.3/libparted/Makefile.am.aix     2003-05-28 02:37:56.000000000 -0400
-+++ parted-1.6.3/libparted/Makefile.am 2003-05-28 02:38:13.000000000 -0400
-@@ -47,6 +47,7 @@
-                       disk_pc98.c             \
-                       disk_sun.c              \
-                       disk_amiga.c            \
-+                      disk_aix.c              \
-                       @OS@.c
- EXTRA_libparted_la_SOURCES    = linux.c               \
---- parted-1.6.3/libparted/disk_dos.c.aix      2003-05-28 01:34:04.000000000 -0400
-+++ parted-1.6.3/libparted/disk_dos.c  2003-05-28 01:59:53.000000000 -0400
-@@ -153,6 +153,13 @@
-                       return 0;
-       }
-+      /* If this is an AIX Physical Volume, fail here.  IBMA in EBCDIC */
-+      if (part_table.boot_code[0] == (char) 0xc9 && 
-+          part_table.boot_code[1] == (char) 0xc2 &&
-+          part_table.boot_code[2] == (char) 0xd4 && 
-+          part_table.boot_code[3] == (char) 0xc1)
-+              return 0;
-+
- #ifdef ENABLE_PC98
-       /* HACK: it's impossible to tell PC98 and msdos disk labels apart.
-        * Someone made the signatures the same (very clever).  Since
---- parted-1.6.23/libparted/libparted.c.orig   2005-07-18 20:57:53.057531736 +0200
-+++ parted-1.6.23/libparted/libparted.c        2005-07-18 20:59:01.716094048 +0200
-@@ -78,6 +78,7 @@
-       return 1;
- }
-+extern void ped_disk_aix_init ();
- extern void ped_disk_bsd_init ();
- extern void ped_disk_dvh_init ();
- extern void ped_disk_gpt_init ();
-@@ -108,6 +109,7 @@
-       ped_disk_dvh_init ();
-       ped_disk_bsd_init ();
-       ped_disk_amiga_init ();
-+      ped_disk_aix_init ();
- }
- #ifdef ENABLE_FS
-@@ -138,6 +140,7 @@
- }
- #endif /* ENABLE_FS */
-+extern void ped_disk_aix_done ();
- extern void ped_disk_bsd_done ();
- extern void ped_disk_dvh_done ();
- extern void ped_disk_gpt_done ();
-@@ -166,6 +169,7 @@
-       ped_disk_dvh_done ();
-       ped_disk_bsd_done ();
-       ped_disk_amiga_done ();
-+      ped_disk_aix_done ();
- }
- static void _init() __attribute__ ((constructor));
index 653785830286d85b946f1c4684b510d78ce3c2b0..5917a87f722c4ec93e9ffd8c0af5b098074c57af 100644 (file)
---- parted-1.6.25/include/parted/device.h.orig 2005-10-19 22:13:26.000000000 +0200
-+++ parted-1.6.25/include/parted/device.h      2005-11-04 10:03:56.934241352 +0100
-@@ -33,7 +33,8 @@
-       PED_DEVICE_FILE         = 5,
-       PED_DEVICE_ATARAID      = 6,
-       PED_DEVICE_I2O          = 7,
--      PED_DEVICE_UBD          = 8
-+      PED_DEVICE_UBD          = 8,
-+      PED_DEVICE_DASD         = 9
+diff -urN parted-1.7.0.orig/include/parted/device.h parted-1.7.0/include/parted/device.h
+--- parted-1.7.0.orig/include/parted/device.h  2006-05-19 14:37:18.000000000 -0400
++++ parted-1.7.0/include/parted/device.h       2006-05-19 14:37:55.000000000 -0400
+@@ -43,6 +43,7 @@
+         PED_DEVICE_ATARAID      = 6,
+         PED_DEVICE_I2O          = 7,
+         PED_DEVICE_UBD          = 8,
++        PED_DEVICE_DASD         = 9,
+         PED_DEVICE_SX8          = 11
  } PedDeviceType;
  
- typedef struct _PedDevice PedDevice;
-diff -ruN --minimal parted-1.6.21.orig/include/parted/disk.h parted-1.6.21/include/parted/disk.h
---- parted-1.6.21.orig/include/parted/disk.h   2005-01-04 11:09:50.000000000 -0500
-+++ parted-1.6.21/include/parted/disk.h        2005-01-21 15:00:40.422628505 -0500
-@@ -36,7 +36,8 @@
-       PED_PARTITION_LOGICAL           = 0x01,
-       PED_PARTITION_EXTENDED          = 0x02,
-       PED_PARTITION_FREESPACE         = 0x04,
--      PED_PARTITION_METADATA          = 0x08
-+      PED_PARTITION_METADATA          = 0x08,
-+      PED_PARTITION_PROTECTED         = 0x10
+diff -urN parted-1.7.0.orig/include/parted/disk.h parted-1.7.0/include/parted/disk.h
+--- parted-1.7.0.orig/include/parted/disk.h    2006-05-15 05:49:54.000000000 -0400
++++ parted-1.7.0/include/parted/disk.h 2006-05-19 14:37:55.000000000 -0400
+@@ -46,7 +46,8 @@
+         PED_PARTITION_LOGICAL           = 0x01,
+         PED_PARTITION_EXTENDED          = 0x02,
+         PED_PARTITION_FREESPACE         = 0x04,
+-        PED_PARTITION_METADATA          = 0x08
++        PED_PARTITION_METADATA          = 0x08,
++        PED_PARTITION_PROTECTED         = 0x10
  } PedPartitionType;
  
- typedef enum {
-diff -ruN --minimal parted-1.6.21.orig/include/parted/linux.h parted-1.6.21/include/parted/linux.h
---- parted-1.6.21.orig/include/parted/linux.h  2001-12-26 19:26:08.000000000 -0500
-+++ parted-1.6.21/include/parted/linux.h       2005-01-21 15:00:40.422628505 -0500
-@@ -29,6 +29,11 @@
- struct _LinuxSpecific {
-       int     fd;
-+#if defined(__s390__) || defined(__s390x__)
-+      unsigned int    real_sector_size;
-+        /* IBM internal dasd structure (i guess ;), required. */
-+        struct fdasd_anchor  *anchor;
-+#endif
- };
- extern PedArchitecture ped_linux_arch;
-diff -ruN --minimal parted-1.6.21.orig/libparted/Makefile.am parted-1.6.21/libparted/Makefile.am
---- parted-1.6.21.orig/libparted/Makefile.am   2005-01-05 18:16:52.000000000 -0500
-+++ parted-1.6.21/libparted/Makefile.am        2005-01-21 15:00:40.423628479 -0500
-@@ -35,6 +35,11 @@
-                       timer.c                 \
-                       disk.c                  \
-                       disk_bsd.c              \
-+                      disk_dasd.c             \
-+                      fdasd.c                 \
-+                      fdasd.h                 \
-+                      vtoc.c                  \
-+                      vtoc.h                  \
-                       disk_dos.c              \
-                       disk_gpt.c              \
-                       disk_loop.c             \
-diff -ruN --minimal parted-1.6.21.orig/libparted/disk_dasd.c parted-1.6.21/libparted/disk_dasd.c
---- parted-1.6.21.orig/libparted/disk_dasd.c   1969-12-31 19:00:00.000000000 -0500
-+++ parted-1.6.21/libparted/disk_dasd.c        2005-01-21 15:00:40.425628426 -0500
-@@ -0,0 +1,882 @@
-+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ /**
+diff -urN parted-1.7.0.orig/include/parted/fdasd.h parted-1.7.0/include/parted/fdasd.h
+--- parted-1.7.0.orig/include/parted/fdasd.h   1969-12-31 19:00:00.000000000 -0500
++++ parted-1.7.0/include/parted/fdasd.h        2006-05-19 14:37:55.000000000 -0400
+@@ -0,0 +1,230 @@
++/*
++ * File...........: s390-tools/fdasd/fdasd.h
++ * Author(s)......: Volker Sameske <sameske@de.ibm.com>
++ *                  Horst Hummel   <Horst.Hummel@de.ibm.com>
++ * Bugreports.to..: <Linux390@de.ibm.com>
++ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2001-2002
++ *
++ * History of changes (starts March 2001)
++ * version 1.01 - menu entry 's' to show mapping devnode - DS name
++ *         1.02 - DS names count now from 0001 instead from 0000
++ *         1.03 - volser checks: 'AA AAA' to 'AAAAA '
++ *              - removed dependency to kernel headers.
++ *         1.04 - added -p option
++ *         1.05 - new API policy, set it back to 0
++ */
++#ifndef FDASD_H
++#define FDASD_H
 +
-+    libparted - a library for manipulating disk partitions
-+    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
++/*****************************************************************************
++ * SECTION: Definitions needed for DASD-API (see dasd.h)                     *
++ *****************************************************************************/
 +
-+    This program is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU General Public License as published by
-+    the Free Software Foundation; either version 2 of the License, or
-+    (at your option) any later version.
++#define DASD_IOCTL_LETTER 'D'
 +
-+    This program is distributed in the hope that it will be useful,
-+    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+    GNU General Public License for more details.
++#define DASD_PARTN_BITS 2
 +
-+    You should have received a copy of the GNU General Public License
-+    along with this program; if not, write to the Free Software
-+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++#define PARTITION_LINUX_SWAP    0x82
++#define PARTITION_LINUX         0x83
++#define PARTITION_LINUX_EXT     0x85
++#define PARTITION_LINUX_LVM     0x8e
++#define PARTITION_LINUX_RAID    0xfd
++#define PARTITION_LINUX_LVM_OLD 0xfe
 +
-+    Contributor:  Phil Knirsch <phil@redhat.de>
-+                  Harald Hoyer <harald@redhat.de>
-+*/
++#define PART_TYPE_NATIVE "NATIVE"
++#define PART_TYPE_SWAP   "SWAP  "
++#define PART_TYPE_RAID   "RAID  "
++#define PART_TYPE_LVM   "LVM   "
 +
-+#include "config.h"
++#ifdef DEBUG_DASD
++#define PDEBUG           fprintf(stderr, "%s:%d:%s\n", \
++                         __FILE__,                              \
++                         __LINE__,                              \
++                         __PRETTY_FUNCTION__);
++#else
++#define PDEBUG
++#endif
 +
-+#include <string.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <fcntl.h>
-+#include <unistd.h>
++/* 
++ * struct dasd_information_t
++ * represents any data about the device, which is visible to userspace.
++ *  including foramt and featueres.
++ */
++typedef struct dasd_information_t {
++        unsigned int devno;           /* S/390 devno                         */
++        unsigned int real_devno;      /* for aliases                         */
++        unsigned int schid;           /* S/390 subchannel identifier         */
++        unsigned int cu_type  : 16;   /* from SenseID                        */
++        unsigned int cu_model :  8;   /* from SenseID                        */
++        unsigned int dev_type : 16;   /* from SenseID                        */
++        unsigned int dev_model : 8;   /* from SenseID                        */
++        unsigned int open_count; 
++        unsigned int req_queue_len; 
++        unsigned int chanq_len;       /* length of chanq                     */
++        char type[4];                 /* from discipline.name, 'none' for    */
++                                    /* unknown                             */
++        unsigned int status;          /* current device level                */
++        unsigned int label_block;     /* where to find the VOLSER            */
++        unsigned int FBA_layout;      /* fixed block size (like AIXVOL)      */
++        unsigned int characteristics_size;
++        unsigned int confdata_size;
++        char characteristics[64];     /* from read_device_characteristics    */
++        char configuration_data[256]; /* from read_configuration_data        */
++} dasd_information_t;
 +
-+#include <sys/stat.h>
-+#include <sys/ioctl.h>
-+#include <parted/parted.h>
-+#include <parted/endian.h>
-+#include <parted/debug.h>
++/* 
++ * struct format_data_t
++ * represents all data necessary to format a dasd
++ */
++typedef struct format_data_t {
++      int start_unit; /* from track */
++      int stop_unit;  /* to track */
++      int blksize;    /* sectorsize */
++        int intensity;  
++} format_data_t;
 +
-+#include "vtoc.h"
-+#include "fdasd.h"
-+#include <parted/linux.h>
++/*
++ * values to be used for format_data_t.intensity
++ * 0/8: normal format
++ * 1/9: also write record zero
++ * 3/11: also write home address
++ * 4/12: invalidate track
++ */
++#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
++#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
++#define DASD_FMT_INT_INVAL  4 /* invalidate tracks */
++#define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
 +
-+#include <libintl.h>
-+#if ENABLE_NLS
-+#  define _(String) dgettext (PACKAGE, String)
-+#else
-+#  define _(String) (String)
-+#endif /* ENABLE_NLS */
 +
++/* Disable the volume (for Linux) */
++#define BIODASDDISABLE _IO(DASD_IOCTL_LETTER,0) 
++/* Enable the volume (for Linux) */
++#define BIODASDENABLE  _IO(DASD_IOCTL_LETTER,1)  
 +
-+#define PARTITION_LINUX_SWAP  0x82
-+#define PARTITION_LINUX               0x83
-+#define PARTITION_LINUX_EXT   0x85
-+#define PARTITION_LINUX_LVM   0x8e
-+#define PARTITION_LINUX_RAID  0xfd
-+#define PARTITION_LINUX_LVM_OLD 0xfe
++/* retrieve API version number */
++#define DASDAPIVER     _IOR(DASD_IOCTL_LETTER,0,int)
++/* Get information on a dasd device (enhanced) */
++#define BIODASDINFO   _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
 +
 +
-+extern void ped_disk_dasd_init ();
-+extern void ped_disk_dasd_done ();
++/*****************************************************************************
++ * SECTION: Further IOCTL Definitions  (see fs.h)                            *
++ *****************************************************************************/
++/* re-read partition table */
++#define BLKRRPART  _IO(0x12,95)       
++/* get block device sector size */
++#define BLKSSZGET  _IO(0x12,104)
 +
++/*****************************************************************************
++ * SECTION: Definition from hdreq.h                                          *
++ *****************************************************************************/
 +
-+#define DASD_NAME "dasd"
++struct fdasd_hd_geometry {
++      unsigned char heads;
++      unsigned char sectors;
++      unsigned short cylinders;
++      unsigned long start;
++};
 +
-+typedef struct {
-+      int type;
-+        int system;
-+      int             raid;
-+      int             lvm;
-+  void            *part_info;
-+} DasdPartitionData;
++/* get device geometry */
++#define HDIO_GETGEO           0x0301  
 +
-+typedef struct {
-+        unsigned int  real_sector_size;
-+        unsigned int  format_type;
-+        /* IBM internal dasd structure (i guess ;), required. */
-+        struct fdasd_anchor  *anchor;
-+} DasdDiskSpecific;
++/*****************************************************************************
++ * SECTION: FDASD internal types                                             *
++ *****************************************************************************/
 +
-+static int dasd_probe (PedDevice *dev);
-+static int dasd_clobber (PedDevice* dev);
-+static int dasd_read (PedDisk* disk);
-+static int dasd_write (PedDisk* disk);
++#define DASD_MIN_API_VERSION 0
 +
-+static PedPartition* dasd_partition_new (
-+      const PedDisk* disk, PedPartitionType part_type,
-+              const PedFileSystemType* fs_type, PedSector start, PedSector end);
-+static void dasd_partition_destroy (PedPartition* part);
-+static int dasd_partition_set_flag (
-+      PedPartition* part, PedPartitionFlag flag, int state);
-+static int dasd_partition_get_flag (
-+      const PedPartition* part, PedPartitionFlag flag);
-+static int dasd_partition_is_flag_available (
-+      const PedPartition* part,
-+      PedPartitionFlag flag);
-+static int dasd_partition_align (PedPartition* part,
-+                                const PedConstraint* constraint);
-+static int dasd_partition_enumerate (PedPartition* part);
-+static int dasd_get_max_primary_partition_count (const PedDisk* disk);
++#define DEFAULT_FDASD_CONF "/etc/fdasd.conf" /* default config file */
 +
-+static PedDisk* dasd_alloc (PedDevice* dev);
-+static PedDisk* dasd_duplicate (const PedDisk* disk);
-+static void dasd_free (PedDisk* disk);
-+static int dasd_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type);
-+static int dasd_alloc_metadata (PedDisk* disk);
++#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
++#define USABLE_PARTITIONS ((1 << DASD_PARTN_BITS) - 1)
 +
-+static PedDiskOps dasd_disk_ops = {
-+      probe:                  dasd_probe,
-+      clobber:                dasd_clobber,
-+      read:                   dasd_read,
-+      write:                  dasd_write,
++#define FDASD_VERSION "1.05"
++#define FDASD_ERROR "fdasd error: "
++#define DEVICE "device"
++#define DISC   "disc"
++#define PART   "part"
 +
-+      alloc: dasd_alloc,
-+      duplicate: dasd_duplicate,
-+      free: dasd_free,
-+      partition_set_system:   dasd_partition_set_system,
-+      
-+      partition_new:          dasd_partition_new,
-+      partition_destroy:      dasd_partition_destroy,
-+      partition_set_flag:     dasd_partition_set_flag,
-+      partition_get_flag:     dasd_partition_get_flag,
-+      partition_is_flag_available:    dasd_partition_is_flag_available,
-+      partition_set_name:     NULL,
-+      partition_get_name:     NULL,
-+      partition_align:        dasd_partition_align,
-+      partition_enumerate:    dasd_partition_enumerate,
++#define ALTERNATE_CYLINDERS_USED 0x10
 +
-+      alloc_metadata:         dasd_alloc_metadata,
-+      get_max_primary_partition_count:
-+        dasd_get_max_primary_partition_count,
++typedef struct partition_info {
++        u_int8_t           used;
++        unsigned long      start_trk;
++        unsigned long      end_trk;
++        unsigned long      len_trk;
++        unsigned long      fspace_trk;
++        format1_label_t  * f1; 
++        struct partition_info *next;
++        struct partition_info *prev;
++        u_int8_t           type;
++} partition_info_t;
 +
-+        partition_duplicate: NULL
-+};
 +
-+static PedDiskType dasd_disk_type = {
-+      next:           NULL,
-+      name:           "dasd",
-+      ops:            &dasd_disk_ops,
-+      features:       0
-+};
-+
-+static PedDisk*
-+dasd_alloc (PedDevice* dev)
-+{
-+      PedDisk* disk;
-+      LinuxSpecific* arch_specific;
-+        DasdDiskSpecific *disk_specific;
-+
-+      PED_ASSERT (dev != NULL, return NULL);
++typedef struct config_data {
++      unsigned long start;
++      unsigned long stop;
++} config_data_t;
 +
-+        arch_specific = LINUX_SPECIFIC (dev);
-+        disk = _ped_disk_alloc (dev, &dasd_disk_type);
-+      if (!disk)
-+                return NULL;
-+        
-+      disk->disk_specific = disk_specific = ped_malloc (sizeof (DasdDiskSpecific));
-+      if (!disk->disk_specific) {
-+                ped_free (disk);
-+                return NULL;
-+        }
-+        
-+        /* because we lie to parted we have to compensate with the
-+           real sector size.  Record that now. */
-+      if (ioctl (arch_specific->fd, BLKSSZGET,
-+                   &disk_specific->real_sector_size) == -1) {
-+                ped_exception_throw (PED_EXCEPTION_ERROR,
-+                                     PED_EXCEPTION_CANCEL,
-+                                     _("Unable to determine the block "
-+                                       "size of this dasd"));
-+                ped_free (disk_specific);
-+                ped_free (disk);
-+                return NULL;
-+        }
 +
-+        return disk;
-+}
++typedef struct fdasd_anchor {
++        int vlabel_changed;
++        int vtoc_changed;
++      int devname_specified;
++      int volid_specified;
++      int config_specified;
++      int auto_partition;
++      int print_table;
++      int big_disk;
++      int silent;
++      int verbose;
++      int devno;
++      int option_reuse;
++      int option_recreate;
++      int partno[USABLE_PARTITIONS];
++      u_int16_t dev_type;
++      unsigned int used_partitions;
++      unsigned long label_pos;
++        unsigned int  blksize;
++        unsigned long fspace_trk;
++        format4_label_t  *f4;
++        format5_label_t  *f5;
++      format7_label_t  *f7;
++        partition_info_t *first;
++        partition_info_t *last;
++        volume_label_t   *vlabel;
++      config_data_t confdata[USABLE_PARTITIONS];
++      struct fdasd_hd_geometry geo;
++} fdasd_anchor_t;
 +
-+static PedDisk*
-+dasd_duplicate (const PedDisk* disk)
-+{
-+      PedDisk*        new_disk;
++enum offset {lower, upper};
 +
-+      new_disk = ped_disk_new_fresh (disk->dev, &dasd_disk_type);
-+      if (!new_disk)
-+              return NULL;
-+      new_disk->disk_specific = NULL;
-+      return new_disk;
-+}
++enum fdasd_failure {
++      unable_to_open_disk,
++      unable_to_seek_disk,
++      unable_to_read_disk,
++      read_only_disk,
++        unable_to_ioctl,
++      api_version_mismatch,
++      wrong_disk_type,
++      wrong_disk_format,
++      disk_in_use,
++      config_syntax_error,
++      vlabel_corrupted,
++      dsname_corrupted,
++      malloc_failed,
++      device_verification_failed
++};
 +
-+static void
-+dasd_free (PedDisk* disk)
-+{
-+      PED_ASSERT (disk != NULL, return);
++void fdasd_cleanup (fdasd_anchor_t *anchor);
++void fdasd_initialize_anchor (fdasd_anchor_t * anc);
++void fdasd_get_geometry (fdasd_anchor_t *anc, int fd);
++void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
++int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
++int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
++int fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc);
++void fdasd_recreate_vtoc(fdasd_anchor_t *anc);
++partition_info_t * fdasd_add_partition (fdasd_anchor_t *anc, unsigned int start, unsigned int stop);
++int fdasd_prepare_labels (fdasd_anchor_t *anc, int fd) ;
 +
-+      _ped_disk_free (disk);
-+}
++#endif /* FDASD_H */
+diff -urN parted-1.7.0.orig/include/parted/linux.h parted-1.7.0/include/parted/linux.h
+--- parted-1.7.0.orig/include/parted/linux.h   2006-05-15 05:19:17.000000000 -0400
++++ parted-1.7.0/include/parted/linux.h        2006-05-19 14:37:55.000000000 -0400
+@@ -29,6 +29,11 @@
+ struct _LinuxSpecific {
+       int     fd;
++#if defined(__s390__) || defined(__s390x__)
++      unsigned int real_sector_size;
++      /* IBM internal dasd structure (i guess ;), required. */
++      struct fdasd_anchor *anchor;
++#endif
+ };
+ extern PedArchitecture ped_linux_arch;
+diff -urN parted-1.7.0.orig/include/parted/vtoc.h parted-1.7.0/include/parted/vtoc.h
+--- parted-1.7.0.orig/include/parted/vtoc.h    1969-12-31 19:00:00.000000000 -0500
++++ parted-1.7.0/include/parted/vtoc.h 2006-05-19 14:37:55.000000000 -0400
+@@ -0,0 +1,371 @@
++/*
++ * File...........: s390-tools/dasdview/vtoc.h
++ * Author(s)......: Horst Hummel <horst.hummel@de.ibm.com>
++ * Bugreports.to..: <Linux390@de.ibm.com>
++ *
++ * This is a user-space copy of the kernel vtoc,h. 
++ * 
++ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2002
++ *
++ * History of changes (starts March 2002)
++ * 2002-03-12 initial
++ */
 +
++#ifndef VTOC_H
++#define VTOC_H
 +
-+void
-+ped_disk_dasd_init ()
-+{
-+      ped_register_disk_type (&dasd_disk_type);
-+}
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#include <ctype.h>
++#include <time.h>
++#include <fcntl.h>
++#include <unistd.h>
 +
-+void
-+ped_disk_dasd_done ()
-+{
-+      ped_unregister_disk_type (&dasd_disk_type);
-+}
++#include <sys/stat.h>
++#include <sys/ioctl.h>
 +
-+static int
-+dasd_probe (PedDevice *dev)
-+{
-+        char *errstr = 0;
-+      LinuxSpecific* arch_specific;
-+        struct fdasd_anchor anchor;
++#define LINE_LENGTH 80
++#define VTOC_START_CC 0x0
++#define VTOC_START_HH 0x1
++#define FIRST_USABLE_CYL 1
++#define FIRST_USABLE_TRK 2
 +
-+      PED_ASSERT (dev != NULL, return 0);
-+      PED_ASSERT ((dev->type == PED_DEVICE_DASD || dev->type == PED_DEVICE_VIODASD), return 0);
++#define DASD_3380_TYPE 13148
++#define DASD_3390_TYPE 13200
++#define DASD_9345_TYPE 37701
 +
-+        arch_specific = LINUX_SPECIFIC (dev);
++#define DASD_3380_VALUE 0xbb60
++#define DASD_3390_VALUE 0xe5a2
++#define DASD_9345_VALUE 0xbc98
 +
-+        /* add partition test here */
-+        fdasd_initialize_anchor(&anchor);
++#define VOLSER_LENGTH 6
++#define BIG_DISK_SIZE 0x10000
 +
-+        fdasd_get_geometry(&anchor, arch_specific->fd);
++#define VTOC_ERROR "VTOC error:"
 +
-+        fdasd_check_api_version(&anchor, arch_specific->fd);
 +
-+        if (fdasd_check_volume(&anchor, arch_specific->fd))
-+                goto error_cleanup;
++typedef struct ttr 
++{
++        u_int16_t tt;
++        u_int8_t  r;
++} __attribute__ ((packed)) ttr_t;
 +
-+        fdasd_cleanup(&anchor);
++typedef struct cchhb 
++{
++        u_int16_t cc;
++        u_int16_t hh;
++        u_int8_t b;
++} __attribute__ ((packed)) cchhb_t;
 +
-+      return 1;
-+error_cleanup:
-+        fdasd_cleanup(&anchor);
-+error:
-+        ped_exception_throw ( PED_EXCEPTION_ERROR,
-+                              PED_EXCEPTION_IGNORE_CANCEL,
-+                              errstr );
++typedef struct cchh 
++{
++        u_int16_t cc;
++        u_int16_t hh;
++} __attribute__ ((packed)) cchh_t;
 +
-+        return 0;
-+}
++typedef struct labeldate 
++{
++        u_int8_t  year;
++        u_int16_t day;
++} __attribute__ ((packed)) labeldate_t;
 +
 +
-+static int
-+dasd_clobber (PedDevice* dev)
++typedef struct volume_label 
 +{
-+        int i;
-+        LinuxSpecific*        arch_specific;
-+        struct fdasd_anchor anchor;
-+
-+      PED_ASSERT (dev != NULL, return 0);
++        char volkey[4];         /* volume key = volume label                 */
++      char vollbl[4];         /* volume label                              */
++      char volid[6];          /* volume identifier                         */
++      u_int8_t security;              /* security byte                             */
++      cchhb_t vtoc;           /* VTOC address                              */
++      char res1[5];           /* reserved                                  */
++        char cisize[4];               /* CI-size for FBA,...                       */
++                                /* ...blanks for CKD                         */
++      char blkperci[4];       /* no of blocks per CI (FBA), blanks for CKD */
++      char labperci[4];       /* no of labels per CI (FBA), blanks for CKD */
++      char res2[4];           /* reserved                                  */
++      char lvtoc[14];         /* owner code for LVTOC                      */
++      char res3[29];          /* reserved                                  */
++} __attribute__ ((packed)) volume_label_t;
 +
-+      arch_specific = LINUX_SPECIFIC (dev);
 +
-+        fdasd_initialize_anchor(&anchor);
-+        fdasd_get_geometry(&anchor, arch_specific->fd);
++typedef struct extent 
++{
++        u_int8_t  typeind;          /* extent type indicator                     */
++        u_int8_t  seqno;            /* extent sequence number                    */
++        cchh_t llimit;          /* starting point of this extent             */
++        cchh_t ulimit;          /* ending point of this extent               */
++} __attribute__ ((packed)) extent_t;
 +
-+        fdasd_recreate_vtoc(&anchor);
-+        fdasd_write_labels(&anchor, arch_specific->fd);
 +
-+      return 1;
-+ error:
-+        return 0;
-+}
++typedef struct dev_const 
++{
++        u_int16_t DS4DSCYL;           /* number of logical cyls                  */
++        u_int16_t DS4DSTRK;           /* number of tracks in a logical cylinder  */
++        u_int16_t DS4DEVTK;           /* device track length                     */
++        u_int8_t  DS4DEVI;            /* non-last keyed record overhead          */
++        u_int8_t  DS4DEVL;            /* last keyed record overhead              */
++        u_int8_t  DS4DEVK;            /* non-keyed record overhead differential  */
++        u_int8_t  DS4DEVFG;           /* flag byte                               */
++        u_int16_t DS4DEVTL;           /* device tolerance                        */
++        u_int8_t  DS4DEVDT;           /* number of DSCB's per track              */
++        u_int8_t  DS4DEVDB;           /* number of directory blocks per track    */
++} __attribute__ ((packed)) dev_const_t;
 +
-+static int
-+dasd_read (PedDisk* disk)
++
++typedef struct format1_label 
 +{
-+      int i, s;
-+      char str[20];
-+        PedDevice* dev;
-+      PedPartition* part;
-+      PedSector start, end;
-+      PedConstraint* constraint_exact;
-+      partition_info_t *p;
-+      LinuxSpecific*  arch_specific;
-+        DasdDiskSpecific* disk_specific;
++      char  DS1DSNAM[44];       /* data set name                           */
++      u_int8_t  DS1FMTID;           /* format identifier                       */
++      char  DS1DSSN[6];         /* data set serial number                  */
++      u_int16_t DS1VOLSQ;           /* volume sequence number                  */
++      labeldate_t DS1CREDT;     /* creation date: ydd                      */
++      labeldate_t DS1EXPDT;     /* expiration date                         */
++      u_int8_t  DS1NOEPV;           /* number of extents on volume             */
++        u_int8_t  DS1NOBDB;           /* no. of bytes used in last direction blk */
++      u_int8_t  DS1FLAG1;           /* flag 1                                  */
++      char  DS1SYSCD[13];       /* system code                             */
++      labeldate_t DS1REFD;      /* date last referenced                    */
++        u_int8_t  DS1SMSFG;           /* system managed storage indicators       */
++        u_int8_t  DS1SCXTF;           /* sec. space extension flag byte          */
++        u_int16_t DS1SCXTV;           /* secondary space extension value         */
++        u_int8_t  DS1DSRG1;           /* data set organisation byte 1            */
++        u_int8_t  DS1DSRG2;           /* data set organisation byte 2            */
++      u_int8_t  DS1RECFM;           /* record format                           */
++      u_int8_t  DS1OPTCD;           /* option code                             */
++      u_int16_t DS1BLKL;            /* block length                            */
++      u_int16_t DS1LRECL;           /* record length                           */
++      u_int8_t  DS1KEYL;            /* key length                              */
++      u_int16_t DS1RKP;             /* relative key position                   */
++      u_int8_t  DS1DSIND;           /* data set indicators                     */
++        u_int8_t  DS1SCAL1;           /* secondary allocation flag byte          */
++      char DS1SCAL3[3];         /* secondary allocation quantity           */
++      ttr_t DS1LSTAR;           /* last used track and block on track      */
++      u_int16_t DS1TRBAL;           /* space remaining on last used track      */
++        u_int16_t res1;               /* reserved                                */
++      extent_t DS1EXT1;         /* first extent description                */
++      extent_t DS1EXT2;         /* second extent description               */
++      extent_t DS1EXT3;         /* third extent description                */
++      cchhb_t DS1PTRDS;         /* possible pointer to f2 or f3 DSCB       */
++} __attribute__ ((packed)) format1_label_t;
 +
-+        PDEBUG;
 +
-+      PED_ASSERT (disk != NULL, return 0);
-+        PDEBUG;
-+      PED_ASSERT (disk->dev != NULL, return 0);
-+        PDEBUG;
++typedef struct format4_label 
++{
++      char  DS4KEYCD[44];       /* key code for VTOC labels: 44 times 0x04 */
++        u_int8_t  DS4IDFMT;           /* format identifier                       */
++      cchhb_t DS4HPCHR;         /* highest address of a format 1 DSCB      */
++        u_int16_t DS4DSREC;           /* number of available DSCB's              */
++        cchh_t DS4HCCHH;          /* CCHH of next available alternate track  */
++        u_int16_t DS4NOATK;           /* number of remaining alternate tracks    */
++        u_int8_t  DS4VTOCI;           /* VTOC indicators                         */
++        u_int8_t  DS4NOEXT;           /* number of extents in VTOC               */
++        u_int8_t  DS4SMSFG;           /* system managed storage indicators       */
++        u_int8_t  DS4DEVAC;           /* number of alternate cylinders. 
++                                     Subtract from first two bytes of 
++                                     DS4DEVSZ to get number of usable
++                                   cylinders. can be zero. valid
++                                   only if DS4DEVAV on.                    */
++        dev_const_t DS4DEVCT;     /* device constants                        */
++        char DS4AMTIM[8];         /* VSAM time stamp                         */
++        char DS4AMCAT[3];         /* VSAM catalog indicator                  */
++        char DS4R2TIM[8];         /* VSAM volume/catalog match time stamp    */
++        char res1[5];             /* reserved                                */
++        char DS4F6PTR[5];         /* pointer to first format 6 DSCB          */
++        extent_t DS4VTOCE;        /* VTOC extent description                 */
++        char res2[10];            /* reserved                                */
++        u_int8_t DS4EFLVL;            /* extended free-space management level    */
++        cchhb_t DS4EFPTR;         /* pointer to extended free-space info     */
++        char res3[9];             /* reserved                                */
++} __attribute__ ((packed)) format4_label_t;
 +
-+        dev = disk->dev;
 +
-+        arch_specific = LINUX_SPECIFIC (dev);
-+        disk_specific = disk->disk_specific;
++typedef struct ds5ext 
++{
++      u_int16_t t;                  /* RTA of the first track of free extent   */
++      u_int16_t fc;                 /* number of whole cylinders in free ext.  */
++      u_int8_t  ft;                 /* number of remaining free tracks         */
++} __attribute__ ((packed)) ds5ext_t;
 +
-+        /* XXX why are we re-creating the anchor? */
-+        if (disk_specific->anchor) {
-+                fdasd_cleanup(disk_specific->anchor);
-+                free(disk_specific->anchor);
-+        }
 +
-+        disk_specific->anchor = ped_malloc(sizeof(fdasd_anchor_t));
++typedef struct format5_label 
++{
++      char DS5KEYID[4];         /* key identifier                          */
++      ds5ext_t DS5AVEXT;        /* first available (free-space) extent.    */
++      ds5ext_t DS5EXTAV[7];     /* seven available extents                 */
++      u_int8_t DS5FMTID;            /* format identifier                       */
++      ds5ext_t DS5MAVET[18];    /* eighteen available extents              */
++      cchhb_t DS5PTRDS;         /* pointer to next format5 DSCB            */
++} __attribute__ ((packed)) format5_label_t;
 +
-+        PDEBUG;
 +
-+        fdasd_initialize_anchor(disk_specific->anchor);
++typedef struct ds7ext 
++{
++      u_int32_t a;                  /* starting RTA value                      */
++      u_int32_t b;                  /* ending RTA value + 1                    */
++} __attribute__ ((packed)) ds7ext_t;
 +
-+        fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
 +
-+      /* check dasd for labels and vtoc */
-+        if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
-+              goto error_close_dev;
++typedef struct format7_label 
++{
++      char DS7KEYID[4];         /* key identifier                          */
++      ds7ext_t DS7EXTNT[5];     /* space for 5 extent descriptions         */
++      u_int8_t DS7FMTID;            /* format identifier                       */
++      ds7ext_t DS7ADEXT[11];    /* space for 11 extent descriptions        */
++      char res1[2];             /* reserved                                */
++      cchhb_t DS7PTRDS;         /* pointer to next FMT7 DSCB               */
++} __attribute__ ((packed)) format7_label_t;
 +
-+      if ((disk_specific->anchor->geo.cylinders * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
-+              disk_specific->anchor->big_disk++;
 +
-+      ped_disk_delete_all (disk);
++char * vtoc_ebcdic_enc (
++        char source[LINE_LENGTH],
++        char target[LINE_LENGTH],
++      int l);
++char * vtoc_ebcdic_dec (
++        char source[LINE_LENGTH],
++      char target[LINE_LENGTH],
++      int l);
++void vtoc_set_extent (
++        extent_t * ext,
++        u_int8_t typeind,
++        u_int8_t seqno,
++        cchh_t * lower,
++        cchh_t * upper);
++void vtoc_set_cchh (
++        cchh_t * addr,
++      u_int16_t cc,
++      u_int16_t hh);
++void vtoc_set_cchhb (
++        cchhb_t * addr,
++        u_int16_t cc,
++        u_int16_t hh,
++        u_int8_t b);
++void vtoc_set_date (
++        labeldate_t * d,
++        u_int8_t year,
++        u_int16_t day);
 +
-+      if (strncmp(disk_specific->anchor->vlabel->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
-+      {
-+                DasdPartitionData*            dasd_data;
++void vtoc_volume_label_init (
++      volume_label_t *vlabel);
 +
-+              /* LDL format, old one */
-+              disk_specific->format_type = 1;
-+              start = 24;
-+              end = (long long)(long long) disk_specific->anchor->geo.cylinders
-+                    * (long long)disk_specific->anchor->geo.heads
-+                    * (long long)disk->dev->hw_geom.sectors
-+                    * (long long)disk_specific->real_sector_size
-+                    / (long long)disk->dev->sector_size - 1;
-+              part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end);
-+              if (!part)
-+                      goto error_close_dev;
-+              part->num = 1;
-+              part->fs_type = ped_file_system_probe (&part->geom);
-+                dasd_data = part->disk_specific;
-+              dasd_data->raid = 0;
-+              dasd_data->lvm = 0;
-+                dasd_data->type = 0;
-+              if (!ped_disk_add_partition (disk, part, NULL))
-+                      goto error_close_dev;
-+              return 1;
-+      }
++int vtoc_read_volume_label (
++        int fd,
++        unsigned long vlabel_start,
++        volume_label_t * vlabel);
 +
-+      /* CDL format, newer */
-+      disk_specific->format_type = 2;
++int vtoc_write_volume_label (
++        int fd,
++        unsigned long vlabel_start,
++        volume_label_t *vlabel);
 +
-+        p = disk_specific->anchor->first;
-+        PDEBUG;
++void vtoc_volume_label_set_volser (
++      volume_label_t *vlabel,
++      char *volser);
 +
-+      for (i = 1 ; i <= USABLE_PARTITIONS; i++)
-+      {
-+                char *ch = p->f1->DS1DSNAM;
-+                DasdPartitionData*            dasd_data;
++char *vtoc_volume_label_get_volser (
++      volume_label_t *vlabel,
++      char *volser);
 +
++void vtoc_volume_label_set_key (
++        volume_label_t *vlabel,
++        char *key);     
 +
-+                if (p->used != 0x01)
-+                        continue;
++void vtoc_volume_label_set_label (
++      volume_label_t *vlabel,
++      char *lbl);
 +
-+        PDEBUG;
++char *vtoc_volume_label_get_label (
++      volume_label_t *vlabel,
++      char *lbl);
 +
-+              start = (long long)(long long) p->start_trk 
-+                        * (long long) disk->dev->hw_geom.sectors 
-+                        * (long long) disk_specific->real_sector_size
-+                        / (long long) disk->dev->sector_size
-+                        ;
-+              end   = (long long)((long long) p->end_trk + 1) 
-+                        * (long long) disk->dev->hw_geom.sectors
-+                        * (long long) disk_specific->real_sector_size 
-+                        / (long long) disk->dev->sector_size 
-+                        - 1;
-+              part = ped_partition_new (disk, 0, NULL, start, end);
-+        PDEBUG;
++void vtoc_read_label (
++        int fd,
++        unsigned long position,
++        format1_label_t *f1,
++        format4_label_t *f4,
++        format5_label_t *f5,
++        format7_label_t *f7);
 +
-+              if (!part)
-+                      goto error_close_dev;
++void vtoc_write_label (
++        int fd,
++        unsigned long position,
++        format1_label_t *f1,
++      format4_label_t *f4,
++      format5_label_t *f5,
++      format7_label_t *f7);
 +
-+        PDEBUG;
 +
-+              part->num = i;
-+              part->fs_type = ped_file_system_probe (&part->geom);
++void vtoc_init_format1_label (
++        char *volid,
++        unsigned int blksize,
++        extent_t *part_extent,
++        format1_label_t *f1);
 +
-+                vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
-+                ch = strstr(p->f1->DS1DSNAM, "PART");
-+                if (ch != NULL) {
-+                        strncpy(str, ch+9, 6);
-+                        str[6] = '\0';
-+                        /*fprintf(stderr, "f1 label contains: >%s<\n", p->f1->DS1DSNAM);
-+                } else {
-+                        strcpy(str, "error");
-+                        fprintf(stderr, "Error, f1 label contains: >%s<\n", p->f1->DS1DSNAM);
-+                      */
-+                }
 +
-+                dasd_data = part->disk_specific;
++void vtoc_init_format4_label (
++        format4_label_t *f4lbl,
++      unsigned int usable_partitions,
++      unsigned int cylinders,
++      unsigned int tracks,
++      unsigned int blocks,
++      unsigned int blksize,
++      u_int16_t dev_type);
 +
-+                if(strncmp(PART_TYPE_RAID, str, 6) == 0)
-+                      ped_partition_set_flag(part, PED_PARTITION_RAID, 1);
-+                else
-+                      ped_partition_set_flag(part, PED_PARTITION_RAID, 0);
++void vtoc_update_format4_label (
++      format4_label_t *f4,
++      cchhb_t *highest_f1,
++      u_int16_t unused_update);
 +
-+                if(strncmp(PART_TYPE_LVM, str, 6) == 0)
-+                      ped_partition_set_flag(part, PED_PARTITION_LVM, 1);
-+                else
-+                      ped_partition_set_flag(part, PED_PARTITION_LVM, 0);
 +
-+                if(strncmp(PART_TYPE_SWAP, str, 6) == 0) {
-+                        dasd_data->system = PARTITION_LINUX_SWAP;
-+                        PDEBUG;
-+                }
++void vtoc_init_format5_label (
++      format5_label_t *f5);
 +
-+                vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++void vtoc_update_format5_label_add (
++      format5_label_t *f5,
++      int verbose,
++      int cyl,
++      int trk,
++      u_int16_t a, 
++      u_int16_t b, 
++      u_int8_t c);
++ 
++void vtoc_update_format5_label_del (
++      format5_label_t *f5,
++      int verbose,
++      int cyl,
++      int trk,
++      u_int16_t a, 
++      u_int16_t b, 
++      u_int8_t c);
 +
-+                dasd_data->part_info = (void *) p;
-+                dasd_data->type = 0;
 +
-+              constraint_exact = ped_constraint_exact (&part->geom);
-+                if(!constraint_exact) 
-+                        goto error_close_dev;
-+              if (!ped_disk_add_partition (disk, part, constraint_exact))
-+                      goto error_close_dev;
-+              ped_constraint_destroy (constraint_exact);
++void vtoc_init_format7_label (
++      format7_label_t *f7);
 +
-+                if (p->fspace_trk > 0) {
-+                        start = (long long)((long long) p->end_trk + 1)
-+                                * (long long) disk->dev->hw_geom.sectors 
-+                                * (long long) disk_specific->real_sector_size
-+                                / (long long) disk->dev->sector_size
-+                                ;
-+                        end   = (long long)((long long) p->end_trk + 1 + p->fspace_trk) 
-+                                * (long long) disk->dev->hw_geom.sectors
-+                                * (long long) disk_specific->real_sector_size 
-+                                / (long long) disk->dev->sector_size 
-+                                - 1;
-+                        part = ped_partition_new (disk, 0, NULL, start, end);
-+                        if (!part)
-+                                goto error_close_dev;
-+                        part->type = PED_PARTITION_FREESPACE;
-+                        constraint_exact = ped_constraint_exact (&part->geom);
-+                        if(!constraint_exact) 
-+                                goto error_close_dev;
-+                        if (!ped_disk_add_partition (disk, part, constraint_exact))
-+                                goto error_close_dev;
-+                        ped_constraint_destroy (constraint_exact);
-+                }
++void vtoc_update_format7_label_add (
++      format7_label_t *f7,
++      int verbose,
++      u_int32_t a, 
++      u_int32_t b);
 +
-+              p = p->next;
-+      }
++void vtoc_update_format7_label_del (
++      format7_label_t *f7, 
++      int verbose,
++      u_int32_t a, 
++      u_int32_t b);
 +
-+        PDEBUG;
-+      return 1;
 +
-+error_close_dev:
-+        PDEBUG;
-+      return 0;
-+}
++void vtoc_set_freespace(
++      format4_label_t *f4,
++      format5_label_t *f5,
++      format7_label_t *f7,
++      char ch,
++      int verbose,
++      u_int32_t start,
++      u_int32_t stop,
++      int cyl,
++      int trk);
 +
-+static int
-+dasd_update_type(PedDisk* disk)
-+{
-+      PedPartition*           part;
-+        LinuxSpecific*        arch_specific;
-+        DasdDiskSpecific* disk_specific;
-+        char *sys = NULL;
 +
-+      arch_specific = LINUX_SPECIFIC (disk->dev);
-+        disk_specific = disk->disk_specific;
++#endif /* VTOC_H */
+diff -urN parted-1.7.0.orig/libparted/arch/linux.c parted-1.7.0/libparted/arch/linux.c
+--- parted-1.7.0.orig/libparted/arch/linux.c   2006-05-19 14:37:18.000000000 -0400
++++ parted-1.7.0/libparted/arch/linux.c        2006-05-19 14:38:15.000000000 -0400
+@@ -62,6 +62,9 @@
+ #define HDIO_GETGEO             0x0301  /* get device geometry */
+ #define HDIO_GET_IDENTITY       0x030d  /* get IDE identification info */
++#include <parted/vtoc.h>
++#include <parted/fdasd.h>
 +
-+        PDEBUG;
+ struct hd_geometry {
+         unsigned char heads;
+         unsigned char sectors;
+@@ -229,6 +232,7 @@
+ #define I2O_MAJOR7              86
+ #define I2O_MAJOR8              87
+ #define UBD_MAJOR               98
++#define DASD_MAJOR              94
+ #define SX8_MAJOR1              160
+ #define SX8_MAJOR2              161
+@@ -325,6 +329,8 @@
+                 dev->type = PED_DEVICE_DAC960;
+         } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
+                 dev->type = PED_DEVICE_ATARAID;
++        } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
++                dev->type = PED_DEVICE_DASD;
+         } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
+                 dev->type = PED_DEVICE_SX8;
+         } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
+@@ -404,6 +410,11 @@
+                 dev->sector_size = (long long)sector_size;
+         }
++        /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
++        if (dev->type == PED_DEVICE_DASD) {
++                dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
++        }
 +
-+      for (part = ped_disk_next_partition (disk, NULL); part;
-+           part = ped_disk_next_partition (disk, part)) {
-+                partition_info_t *p;
-+                char *ch = NULL;
-+                DasdPartitionData*            dasd_data;
+         if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
+                 ped_exception_throw (
+                         PED_EXCEPTION_WARNING,
+@@ -814,6 +825,62 @@
+ }
+ static int
++init_dasd (PedDevice* dev, char* model_name)
++{
++        struct stat             dev_stat;
++        PedExceptionOption      ex_status;
++        dasd_information_t      dasd_info;
++        struct hd_geometry      geo;
++        int f, blksize = 0;
++        char *errstr = 0;
 +
-+                PDEBUG;
++        if (!_device_stat (dev, &dev_stat))
++                goto error;
 +
-+                if(part->type & PED_PARTITION_FREESPACE
-+                   || part->type & PED_PARTITION_METADATA) {
-+                        continue;
-+                }
++        if (!ped_device_open (dev))
++                goto error;
 +
-+                PDEBUG;
++        LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
 +
-+                dasd_data = part->disk_specific;
-+                p = dasd_data->part_info;
-+                if (!p ) {
-+                        PDEBUG;
-+                        continue;
-+                }
-+                vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
-+                ch = strstr(p->f1->DS1DSNAM, "PART");
-+                /*fprintf(stderr, "f1 label contains: >%s<\n", p->f1->DS1DSNAM);*/
++        PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
 +
-+                PDEBUG;
-+                if (ch == NULL) {
-+                        vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
-+                        PDEBUG;
-+                        continue;
-+                }
++        dev->length = _device_get_length (dev);
++        if (!dev->length)
++                goto error_close_dev;
 +
-+                ch += 9;
-+                                
-+                switch(dasd_data->system) {
-+                case PARTITION_LINUX_LVM:
-+                        PDEBUG;
-+                        strncpy(ch, PART_TYPE_LVM, 6);
-+                        break;
-+                case PARTITION_LINUX_RAID:
-+                        PDEBUG;
-+                        strncpy(ch, PART_TYPE_RAID, 6);
-+                        break;
-+                case PARTITION_LINUX:
-+                        PDEBUG;
-+                        strncpy(ch, PART_TYPE_NATIVE, 6);
-+                        break;
-+                case PARTITION_LINUX_SWAP:
-+                        PDEBUG;
-+                        strncpy(ch, PART_TYPE_SWAP, 6);
-+                        break;
-+                default:
-+                        PDEBUG;
-+                        strncpy(ch, PART_TYPE_NATIVE, 6);
-+                        break;
-+                }
-+                disk_specific->anchor->vtoc_changed++;
++        _device_set_sector_size (dev);
++        if (!dev->sector_size)
++                goto error_close_dev;
 +
-+                vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++        if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
++                dev->hw_geom.sectors = geo.sectors;
++                dev->hw_geom.heads = geo.heads;
++                dev->hw_geom.cylinders = dev->length / (dev->hw_geom.heads * dev->hw_geom.sectors) / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
++                dev->bios_geom = dev->hw_geom;
++        } else {
++                dev->bios_geom.sectors = 12;
++                dev->bios_geom.heads = 15;
++                dev->bios_geom.cylinders = dev->length / (dev->hw_geom.heads * dev->hw_geom.sectors) / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
++                dev->hw_geom = dev->bios_geom;
 +        }
++
++        dev->model = strdup (model_name);
++
++        ped_device_close (dev);
 +        return 1;
++
++except:
++        ped_exception_throw ( PED_EXCEPTION_ERROR,
++                              PED_EXCEPTION_IGNORE_CANCEL,
++                              errstr );
++
++error_close_dev:
++        ped_device_close (dev);
++error:
++        return 0;
 +}
-+        
++
 +static int
-+dasd_write (PedDisk* disk)
-+{
-+      DasdPartitionData*      dasd_data;
-+      PedPartition*           part;
-+      int                     i;
-+        int ret;
-+      partition_info_t *p;
-+        LinuxSpecific*        arch_specific;
-+        DasdDiskSpecific* disk_specific;
-+      PED_ASSERT (disk != NULL, return 0);
-+      PED_ASSERT (disk->dev != NULL, return 0);
+ init_generic (PedDevice* dev, char* model_name)
+ {
+         struct stat             dev_stat;
+@@ -837,8 +904,9 @@
+                                 PED_EXCEPTION_WARNING,
+                                 PED_EXCEPTION_IGNORE_CANCEL,
+                                 _("Unable to determine geometry of "
+-                                "file/device.  You should not use Parted "
+-                                "unless you REALLY know what you're doing!"));
++                                "file/device %s.  You should not use Parted "
++                                "unless you REALLY know what you're doing!"),
++                                dev->path);
+                 switch (ex_status) {
+                         case PED_EXCEPTION_CANCEL:
+                                 goto error_close_dev;
+@@ -919,6 +987,11 @@
+                         goto error_free_arch_specific;
+                 break;
++        case PED_DEVICE_DASD:
++                if (!init_dasd (dev, _("IBM S390 DASD drive")))
++                        goto error_free_arch_specific;
++                break;
++
+         case PED_DEVICE_CPQARRAY:
+                 if (!init_generic (dev, _("Compaq Smart Array")))
+                         goto error_free_arch_specific;
+@@ -1927,7 +2000,9 @@
+                  * created.  Therefore, if using DevFS, we must get the kernel
+                  * to re-read and grok the partition table.
+                  */
+-                if (_have_blkpg () && !_have_devfs ()) {
++                /* Work around kernel dasd problem so we really do BLKRRPART */
++                if (disk->dev->type != PED_DEVICE_DASD &&
++                    _have_blkpg () && !_have_devfs ()) {
+                         if (_disk_sync_part_table (disk))
+                                 return 1;
+                 }
+diff -urN parted-1.7.0.orig/libparted/labels/Makefile.am parted-1.7.0/libparted/labels/Makefile.am
+--- parted-1.7.0.orig/libparted/labels/Makefile.am     2006-05-15 05:19:34.000000000 -0400
++++ parted-1.7.0/libparted/labels/Makefile.am  2006-05-19 14:37:55.000000000 -0400
+@@ -12,6 +12,11 @@
+ liblabels_la_SOURCES  = rdb.c         \
+                       bsd.c           \
++                      dasd.c          \
++                      fdasd.c         \
++                      fdash.h         \
++                      vtoc.c          \
++                      vtoc.h          \
+                       efi_crc32.c     \
+                       dos.c           \
+                       dvh.h           \
+diff -urN parted-1.7.0.orig/libparted/labels/dasd.c parted-1.7.0/libparted/labels/dasd.c
+--- parted-1.7.0.orig/libparted/labels/dasd.c  1969-12-31 19:00:00.000000000 -0500
++++ parted-1.7.0/libparted/labels/dasd.c       2006-05-19 14:37:55.000000000 -0400
+@@ -0,0 +1,882 @@
++/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 +
-+      arch_specific = LINUX_SPECIFIC (disk->dev);
-+        disk_specific = disk->disk_specific;
++    libparted - a library for manipulating disk partitions
++    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
 +
-+        PDEBUG;
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License, or
++    (at your option) any later version.
 +
-+      /* If formated in LDL, don't write anything. */
-+      if (disk_specific->format_type == 1)
-+              return 1;
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
 +
-+        /* XXX re-initialize anchor? */
-+        fdasd_initialize_anchor(disk_specific->anchor);
-+        fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 +
-+      /* check dasd for labels and vtoc */
-+        if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
-+              goto error;
++    Contributor:  Phil Knirsch <phil@redhat.de>
++                  Harald Hoyer <harald@redhat.de>
++*/
 +
-+      if ((disk_specific->anchor->geo.cylinders * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
-+              disk_specific->anchor->big_disk++;
++#include "config.h"
 +
-+        fdasd_recreate_vtoc(disk_specific->anchor);
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++#include <ctype.h>
++#include <time.h>
++#include <fcntl.h>
++#include <unistd.h>
 +
-+      for (i = 1; i <= USABLE_PARTITIONS; i++) {
-+                unsigned int start, stop;
-+                int type;
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <parted/parted.h>
++#include <parted/endian.h>
++#include <parted/debug.h>
 +
-+                PDEBUG;
-+              part = ped_disk_get_partition (disk, i);
-+              if (!part)
-+                      continue;
++#include <parted/vtoc.h>
++#include <parted/fdasd.h>
++#include <parted/linux.h>
 +
-+                PDEBUG;
++#include <libintl.h>
++#if ENABLE_NLS
++#  define _(String) dgettext (PACKAGE, String)
++#else
++#  define _(String) (String)
++#endif /* ENABLE_NLS */
 +
-+                start = part->geom.start * disk->dev->sector_size 
-+                        / disk_specific->real_sector_size / disk->dev->hw_geom.sectors;
-+                stop = (part->geom.end + 1) 
-+                        * disk->dev->sector_size / disk_specific->real_sector_size
-+                        / disk->dev->hw_geom.sectors - 1;
 +
-+                PDEBUG;
-+                dasd_data = part->disk_specific;
-+                
-+                type = dasd_data->type;
-+                PDEBUG;
-+                /*fprintf(stderr, "Partition %d  %ld - %ld \t", i, part->geom.start, part->geom.end);
-+                fprintf(stderr, "Partition %d  %ld - %ld \n", i, start, stop);
-+              */
++#define PARTITION_LINUX_SWAP  0x82
++#define PARTITION_LINUX               0x83
++#define PARTITION_LINUX_EXT   0x85
++#define PARTITION_LINUX_LVM   0x8e
++#define PARTITION_LINUX_RAID  0xfd
++#define PARTITION_LINUX_LVM_OLD 0xfe
 +
-+                p = fdasd_add_partition(disk_specific->anchor, start, stop);
-+                if(!p) {
-+                        PDEBUG;
-+                        return 0;
-+                }
-+                dasd_data->part_info = (void *) p;
-+              p->type = dasd_data->system;
-+      }
-+        PDEBUG;
 +
-+        if(!fdasd_prepare_labels(disk_specific->anchor, arch_specific->fd))
-+                return 0;
++extern void ped_disk_dasd_init ();
++extern void ped_disk_dasd_done ();
 +
-+        dasd_update_type(disk);
-+        PDEBUG;
 +
-+        if(!fdasd_write_labels(disk_specific->anchor, arch_specific->fd))
-+                return 0;
++#define DASD_NAME "dasd"
 +
-+        return 1;
-+ error:
-+        PDEBUG;
-+      return 0;
-+}
++typedef struct {
++      int type;
++        int system;
++      int             raid;
++      int             lvm;
++  void            *part_info;
++} DasdPartitionData;
 +
-+static PedPartition*
-+dasd_partition_new (const PedDisk* disk, PedPartitionType part_type,
-+                 const PedFileSystemType* fs_type,
-+                 PedSector start, PedSector end)
-+{
-+      PedPartition*           part;
++typedef struct {
++        unsigned int  real_sector_size;
++        unsigned int  format_type;
++        /* IBM internal dasd structure (i guess ;), required. */
++        struct fdasd_anchor  *anchor;
++} DasdDiskSpecific;
 +
-+      part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
-+      if (!part)
-+              goto error;
++static int dasd_probe (const PedDevice *dev);
++static int dasd_clobber (PedDevice* dev);
++static int dasd_read (PedDisk* disk);
++static int dasd_write (PedDisk* disk);
 +
-+        part->disk_specific = ped_malloc (sizeof (DasdPartitionData));
-+      return part;
++static PedPartition* dasd_partition_new (
++      const PedDisk* disk, PedPartitionType part_type,
++              const PedFileSystemType* fs_type, PedSector start, PedSector end);
++static void dasd_partition_destroy (PedPartition* part);
++static int dasd_partition_set_flag (
++      PedPartition* part, PedPartitionFlag flag, int state);
++static int dasd_partition_get_flag (
++      const PedPartition* part, PedPartitionFlag flag);
++static int dasd_partition_is_flag_available (
++      const PedPartition* part,
++      PedPartitionFlag flag);
++static int dasd_partition_align (PedPartition* part,
++                                const PedConstraint* constraint);
++static int dasd_partition_enumerate (PedPartition* part);
++static int dasd_get_max_primary_partition_count (const PedDisk* disk);
 +
-+error:
-+      return 0;
-+}
++static PedDisk* dasd_alloc (const PedDevice* dev);
++static PedDisk* dasd_duplicate (const PedDisk* disk);
++static void dasd_free (PedDisk* disk);
++static int dasd_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type);
++static int dasd_alloc_metadata (PedDisk* disk);
 +
++static PedDiskOps dasd_disk_ops = {
++      probe:                  dasd_probe,
++      clobber:                dasd_clobber,
++      read:                   dasd_read,
++      write:                  dasd_write,
 +
-+static void
-+dasd_partition_destroy (PedPartition* part)
-+{
-+      PED_ASSERT (part != NULL, return);
++      alloc: dasd_alloc,
++      duplicate: dasd_duplicate,
++      free: dasd_free,
++      partition_set_system:   dasd_partition_set_system,
++      
++      partition_new:          dasd_partition_new,
++      partition_destroy:      dasd_partition_destroy,
++      partition_set_flag:     dasd_partition_set_flag,
++      partition_get_flag:     dasd_partition_get_flag,
++      partition_is_flag_available:    dasd_partition_is_flag_available,
++      partition_set_name:     NULL,
++      partition_get_name:     NULL,
++      partition_align:        dasd_partition_align,
++      partition_enumerate:    dasd_partition_enumerate,
 +
-+      if (ped_partition_is_active (part))
-+              ped_free (part->disk_specific);
-+      ped_free (part);
-+}
++      alloc_metadata:         dasd_alloc_metadata,
++      get_max_primary_partition_count:
++        dasd_get_max_primary_partition_count,
 +
++        partition_duplicate: NULL
++};
 +
-+static int
-+dasd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
++static PedDiskType dasd_disk_type = {
++      next:           NULL,
++      name:           "dasd",
++      ops:            &dasd_disk_ops,
++      features:       0
++};
++
++static PedDisk*
++dasd_alloc (const PedDevice* dev)
 +{
-+      PedDisk*                        disk;
-+      PedPartition*                   walk;
-+      DasdPartitionData*              dasd_data;
-+      const PedFileSystemType*        fs_type;
++      PedDisk* disk;
++      LinuxSpecific* arch_specific;
++        DasdDiskSpecific *disk_specific;
 +
-+      PED_ASSERT (part != NULL, return 0);
-+      PED_ASSERT (part->disk_specific != NULL, return 0);
-+      dasd_data = part->disk_specific;
++      PED_ASSERT (dev != NULL, return NULL);
 +
-+      switch (flag) {
-+      case PED_PARTITION_RAID:
-+              if (state) {
-+                      dasd_data->lvm = 0;
-+              }
-+              dasd_data->raid = state;
-+              return ped_partition_set_system (part, part->fs_type);
-+      case PED_PARTITION_LVM:
-+              if (state) {
-+                      dasd_data->raid = 0;
-+              }
-+              dasd_data->lvm = state;
-+              return ped_partition_set_system (part, part->fs_type);
-+      default:
-+              return 0;
-+      }
++        arch_specific = LINUX_SPECIFIC (dev);
++        disk = _ped_disk_alloc (dev, &dasd_disk_type);
++      if (!disk)
++                return NULL;
++        
++      disk->disk_specific = disk_specific = ped_malloc (sizeof (DasdDiskSpecific));
++      if (!disk->disk_specific) {
++                ped_free (disk);
++                return NULL;
++        }
++        
++        /* because we lie to parted we have to compensate with the
++           real sector size.  Record that now. */
++      if (ioctl (arch_specific->fd, BLKSSZGET,
++                   &disk_specific->real_sector_size) == -1) {
++                ped_exception_throw (PED_EXCEPTION_ERROR,
++                                     PED_EXCEPTION_CANCEL,
++                                     _("Unable to determine the block "
++                                       "size of this dasd"));
++                ped_free (disk_specific);
++                ped_free (disk);
++                return NULL;
++        }
++
++        return disk;
 +}
 +
++static PedDisk*
++dasd_duplicate (const PedDisk* disk)
++{
++      PedDisk*        new_disk;
 +
-+static int
-+dasd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
++      new_disk = ped_disk_new_fresh (disk->dev, &dasd_disk_type);
++      if (!new_disk)
++              return NULL;
++      new_disk->disk_specific = NULL;
++      return new_disk;
++}
++
++static void
++dasd_free (PedDisk* disk)
 +{
-+      DasdPartitionData*      dasd_data;
++      PED_ASSERT (disk != NULL, return);
 +
-+      PED_ASSERT (part != NULL, return 0);
-+      PED_ASSERT (part->disk_specific != NULL, return 0);
-+      dasd_data = part->disk_specific;
++      _ped_disk_free (disk);
++}
 +
-+      switch (flag) {
-+      case PED_PARTITION_RAID:
-+              return dasd_data->raid;
 +
-+      case PED_PARTITION_LVM:
-+              return dasd_data->lvm;
++void
++ped_disk_dasd_init ()
++{
++      ped_register_disk_type (&dasd_disk_type);
++}
 +
-+      default:
-+              return 0;
-+      }
++void
++ped_disk_dasd_done ()
++{
++      ped_unregister_disk_type (&dasd_disk_type);
 +}
 +
 +static int
-+dasd_partition_is_flag_available (const PedPartition* part,
-+                               PedPartitionFlag flag)
++dasd_probe (const PedDevice *dev)
 +{
-+      switch (flag) {
-+      case PED_PARTITION_RAID:
-+              return 1;
-+
-+      case PED_PARTITION_LVM:
-+              return 1;
-+
-+      default:
-+              return 0;
-+      }
-+}
++        char *errstr = 0;
++      LinuxSpecific* arch_specific;
++        struct fdasd_anchor anchor;
 +
++      PED_ASSERT (dev != NULL, return 0);
++      PED_ASSERT ((dev->type == PED_DEVICE_DASD || dev->type == PED_DEVICE_VIODASD), return 0);
 +
-+static int
-+dasd_get_max_primary_partition_count (const PedDisk* disk)
-+{
-+        DasdDiskSpecific* disk_specific;
++        arch_specific = LINUX_SPECIFIC (dev);
 +
-+      disk_specific = disk->disk_specific;
-+      /* If formated in LDL, maximum partition number is 1 */
-+      if (disk_specific->format_type == 1)
-+              return 1;
++        /* add partition test here */
++        fdasd_initialize_anchor(&anchor);
 +
-+      return USABLE_PARTITIONS;
-+}
++        fdasd_get_geometry(&anchor, arch_specific->fd);
 +
-+static PedConstraint*
-+_primary_constraint (PedDisk* disk)
-+{
-+      PedAlignment    start_align;
-+      PedAlignment    end_align;
-+      PedGeometry     max_geom;
-+      PedSector       sector_size;
-+        LinuxSpecific*  arch_specific;
-+        DasdDiskSpecific* disk_specific;
++        fdasd_check_api_version(&anchor, arch_specific->fd);
 +
-+        PDEBUG;
++        if (fdasd_check_volume(&anchor, arch_specific->fd))
++                goto error_cleanup;
 +
-+        arch_specific = LINUX_SPECIFIC (disk->dev);
-+        disk_specific = disk->disk_specific;
-+      sector_size = disk_specific->real_sector_size / disk->dev->sector_size;
++        fdasd_cleanup(&anchor);
 +
-+      if (!ped_alignment_init (&start_align, 0, disk->dev->hw_geom.sectors * sector_size))
-+              return NULL;
-+      if (!ped_alignment_init (&end_align, -1, disk->dev->hw_geom.sectors * sector_size))
-+              return NULL;
-+      if (!ped_geometry_init (&max_geom, disk->dev, 0, disk->dev->length))
-+              return NULL;
++      return 1;
++error_cleanup:
++        fdasd_cleanup(&anchor);
++error:
++        ped_exception_throw ( PED_EXCEPTION_ERROR,
++                              PED_EXCEPTION_IGNORE_CANCEL,
++                              errstr );
 +
-+      return ped_constraint_new (&start_align, &end_align, &max_geom,
-+                                 &max_geom, 1, disk->dev->length);
++        return 0;
 +}
 +
++
 +static int
-+dasd_partition_align (PedPartition* part, const PedConstraint* constraint)
++dasd_clobber (PedDevice* dev)
 +{
-+        DasdDiskSpecific* disk_specific;
-+
-+      PED_ASSERT (part != NULL, return 0);
-+
-+      disk_specific = part->disk->disk_specific;
-+      /* If formated in LDL, ignore metadata partition */
-+      if (disk_specific->format_type == 1)
-+              return 1;
++        int i;
++        LinuxSpecific*        arch_specific;
++        struct fdasd_anchor anchor;
 +
-+      if (_ped_partition_attempt_align (part, constraint,
-+                                        _primary_constraint (part->disk)))
-+              return 1;
++      PED_ASSERT (dev != NULL, return 0);
 +
-+#ifndef DISCOVER_ONLY
-+      ped_exception_throw (
-+              PED_EXCEPTION_ERROR,
-+              PED_EXCEPTION_CANCEL,
-+              _("Unable to satisfy all constraints on the partition."));
-+#endif
-+      return 0;
-+}
++      arch_specific = LINUX_SPECIFIC (dev);
 +
++        fdasd_initialize_anchor(&anchor);
++        fdasd_get_geometry(&anchor, arch_specific->fd);
 +
-+static int
-+dasd_partition_enumerate (PedPartition* part)
-+{
-+      int i;
-+      PedPartition* p;
-+      
-+      /* never change the partition numbers */
-+      if (part->num != -1)
-+              return 1;
-+      for (i = 1; i <= USABLE_PARTITIONS; i++) {
-+              p = ped_disk_get_partition (part->disk, i);
-+              if (!p) {
-+                      part->num = i;
-+                      return 1;
-+              }
-+      }
++        fdasd_recreate_vtoc(&anchor);
++        fdasd_write_labels(&anchor, arch_specific->fd);
 +
-+      /* failed to allocate a number */
-+      ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-+                           _("Unable to allocate a dasd disklabel slot"));
-+      return 0;
++      return 1;
++ error:
++        return 0;
 +}
 +
 +static int
-+dasd_partition_set_system (PedPartition* part,
-+                          const PedFileSystemType* fs_type)
++dasd_read (PedDisk* disk)
 +{
-+      DasdPartitionData* dasd_data = part->disk_specific;
-+      PedSector cyl_size = part->disk->dev->hw_geom.sectors * part->disk->dev->hw_geom.heads;
++      int i, s;
++      char str[20];
++        PedDevice* dev;
++      PedPartition* part;
++      PedSector start, end;
++      PedConstraint* constraint_exact;
++      partition_info_t *p;
++      LinuxSpecific*  arch_specific;
++        DasdDiskSpecific* disk_specific;
 +
 +        PDEBUG;
 +
-+      part->fs_type = fs_type;
-+
-+      if (dasd_data->lvm) {
-+              dasd_data->system = PARTITION_LINUX_LVM;
-+        PDEBUG;
-+              return 1;
-+      }
-+      if (dasd_data->raid) {
-+              dasd_data->system = PARTITION_LINUX_RAID;
-+        PDEBUG;
-+              return 1;
-+      }
-+      if (!fs_type) {
-+              dasd_data->system = PARTITION_LINUX;
-+        PDEBUG;
-+      } else if (!strcmp (fs_type->name, "linux-swap")) {
-+              dasd_data->system = PARTITION_LINUX_SWAP;
++      PED_ASSERT (disk != NULL, return 0);
 +        PDEBUG;
-+        } else {
-+              dasd_data->system = PARTITION_LINUX;
++      PED_ASSERT (disk->dev != NULL, return 0);
 +        PDEBUG;
-+        }
-+
-+      return 1;
-+}
-+
-+static int
-+dasd_alloc_metadata (PedDisk* disk)
-+{
-+      PedPartition*           new_part;
-+      PedConstraint*          constraint_any = NULL;
-+        PedSector             vtoc_end;
-+        LinuxSpecific*                arch_specific;
-+        DasdDiskSpecific*     disk_specific;
 +
-+      PED_ASSERT (disk != NULL, goto error);
-+      PED_ASSERT (disk->dev != NULL, goto error);
++        dev = disk->dev;
 +
-+      arch_specific = LINUX_SPECIFIC (disk->dev);
++        arch_specific = LINUX_SPECIFIC (dev);
 +        disk_specific = disk->disk_specific;
 +
-+      constraint_any = ped_constraint_any (disk->dev);
-+
-+      /* If formated in LDL, the real partition starts at sector 24. */
-+      if (disk_specific->format_type == 1)
-+              vtoc_end = 23;
-+        else
-+        /* Mark the start of the disk as metadata. */
-+              vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors 
-+                              * (long long) disk_specific->real_sector_size
-+                              / (long long) disk->dev->sector_size) - 1;
-+      new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
-+                                      0, vtoc_end);
-+      if (!new_part)
-+              goto error;
-+
-+      if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
-+              ped_partition_destroy (new_part);
-+              goto error;
-+      }
++        /* XXX why are we re-creating the anchor? */
++        if (disk_specific->anchor) {
++                fdasd_cleanup(disk_specific->anchor);
++                free(disk_specific->anchor);
++        }
 +
-+      ped_constraint_destroy (constraint_any);
-+      return 1;
-+error:
-+      ped_constraint_destroy (constraint_any);
-+      return 0;
-+}
-diff -ruN --minimal parted-1.6.21.orig/libparted/fdasd.c parted-1.6.21/libparted/fdasd.c
---- parted-1.6.21.orig/libparted/fdasd.c       1969-12-31 19:00:00.000000000 -0500
-+++ parted-1.6.21/libparted/fdasd.c    2005-01-21 15:00:40.428628348 -0500
-@@ -0,0 +1,1302 @@
-+/*
-+ * File...........: arch/s390/tools/fdasd.c
-+ * Author(s)......: Volker Sameske <sameske@de.ibm.com>
-+ * Bugreports.to..: <Linux390@de.ibm.com>
-+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2001
-+ *
-+ * History of changes (starts March 2001)
-+ * 2001-04-11 possibility to change volume serial added
-+ *            possibility to change partition type added
-+ *            some changes to DS4HPCHR and DS4DSREC
-+ * 2001-05-03 check for invalid partition numbers added
-+ *            wrong free_space calculation bug fixed
-+ * 2001-06-26 '-a' option added, it is now possible to add a single
-+ *            partition in non-interactive mode
-+ * 2001-06-26 long parameter support added
-+ *           
-+ */
-+#include "vtoc.h"
-+#include "fdasd.h"
++        disk_specific->anchor = ped_malloc(sizeof(fdasd_anchor_t));
 +
-+#include <parted/parted.h>
++        PDEBUG;
 +
-+#include <libintl.h>
-+#if ENABLE_NLS
-+#  define _(String) dgettext (PACKAGE, String)
-+#else
-+#  define _(String) (String)
-+#endif /* ENABLE_NLS */
++        fdasd_initialize_anchor(disk_specific->anchor);
 +
++        fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
 +
-+#define GETARG(x) {int k=strlen(optarg);x=malloc(k);strncpy(x,optarg,k);}
++      /* check dasd for labels and vtoc */
++        if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
++              goto error_close_dev;
 +
-+static int
-+getpos (fdasd_anchor_t *anc, int dsn)
-+{
-+PDEBUG
-+      return anc->partno[dsn];
-+}
++      if ((disk_specific->anchor->geo.cylinders * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
++              disk_specific->anchor->big_disk++;
 +
-+static int
-+getdsn (fdasd_anchor_t *anc, int pos)
-+{
-+PDEBUG
-+      int i;
++      ped_disk_delete_all (disk);
 +
-+      for (i=0; i<USABLE_PARTITIONS; i++)
++      if (strncmp(disk_specific->anchor->vlabel->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
 +      {
-+              if (anc->partno[i] == pos)
-+                      return i;
-+      }
++                DasdPartitionData*            dasd_data;
 +
-+      return -1;
-+}
-+
-+static void
-+setpos (fdasd_anchor_t *anc, int dsn, int pos)
-+{
-+PDEBUG
-+      anc->partno[dsn] = pos;
-+}
-+
-+
-+static void
-+fdasd_check_volser (char *s, int devno)
-+{
-+PDEBUG
-+  int i, j;
++              /* LDL format, old one */
++              disk_specific->format_type = 1;
++              start = 24;
++              end = (long long)(long long) disk_specific->anchor->geo.cylinders
++                    * (long long)disk_specific->anchor->geo.heads
++                    * (long long)disk->dev->hw_geom.sectors
++                    * (long long)disk_specific->real_sector_size
++                    / (long long)disk->dev->sector_size - 1;
++              part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end);
++              if (!part)
++                      goto error_close_dev;
++              part->num = 1;
++              part->fs_type = ped_file_system_probe (&part->geom);
++                dasd_data = part->disk_specific;
++              dasd_data->raid = 0;
++              dasd_data->lvm = 0;
++                dasd_data->type = 0;
++              if (!ped_disk_add_partition (disk, part, NULL))
++                      goto error_close_dev;
++              return 1;
++      }
 +
-+  for (i = 0; i < 6; i++)
-+    {
-+      if ((s[i] < 0x20) || (s[i] > 0x7a) || ((s[i] >= 0x21) && (s[i] <= 0x22)) ||      /* !"         */
-+         ((s[i] >= 0x26) && (s[i] <= 0x2f)) || /* &'()*+,-./ */
-+         ((s[i] >= 0x3a) && (s[i] <= 0x3f)) || /* :;<=>?     */
-+         ((s[i] >= 0x5b) && (s[i] <= 0x60)))   /* \]^_´     */
-+       s[i] = ' ';
-+      s[i] = toupper (s[i]);
-+    }
-+  s[6] = 0x00;
++      /* CDL format, newer */
++      disk_specific->format_type = 2;
 +
-+  for (i = 0; i < 6; i++)
-+    {
-+      if (s[i] == ' ')
-+       for (j = i; j < 6; j++)
-+         if (s[j] != ' ')
-+           {
-+             s[i] = s[j];
-+             s[j] = ' ';
-+             break;
-+           }
-+    }
++        p = disk_specific->anchor->first;
++        PDEBUG;
 +
-+  if (s[0] == ' ')
-+    {
-+      printf ("Usage error, switching to default.\n");
-+      sprintf (s, "0X%04x", devno);
-+      for (i = 0; i < 6; i++)
-+       s[i] = toupper (s[i]);
-+    }
-+}
++      for (i = 1 ; i <= USABLE_PARTITIONS; i++)
++      {
++                char *ch = p->f1->DS1DSNAM;
++                DasdPartitionData*            dasd_data;
 +
-+/*
-+ *
-+ */
-+void
-+fdasd_cleanup (fdasd_anchor_t *anchor) 
-+{
-+PDEBUG
-+        int i;
-+        partition_info_t *p, *q;
 +
-+        if (anchor == NULL) return;
++                if (p->used != 0x01)
++                        continue;
 +
-+      if (anchor->f4 != NULL) free(anchor->f4);
-+      if (anchor->f5 != NULL) free(anchor->f5);
-+      if (anchor->f7 != NULL) free(anchor->f7);
-+      if (anchor->vlabel != NULL) free(anchor->vlabel);
++        PDEBUG;
 +
-+      p = anchor->first;
-+      if (p == NULL)
-+              return;
++              start = (long long)(long long) p->start_trk 
++                        * (long long) disk->dev->hw_geom.sectors 
++                        * (long long) disk_specific->real_sector_size
++                        / (long long) disk->dev->sector_size
++                        ;
++              end   = (long long)((long long) p->end_trk + 1) 
++                        * (long long) disk->dev->hw_geom.sectors
++                        * (long long) disk_specific->real_sector_size 
++                        / (long long) disk->dev->sector_size 
++                        - 1;
++              part = ped_partition_new (disk, 0, NULL, start, end);
++        PDEBUG;
 +
-+        for (i=1; i <= USABLE_PARTITIONS; i++) 
-+      {
-+              if (p == NULL)
-+                      return;
-+              q = p->next;
-+              free(p);
-+              p = q;
-+      }
-+}
++              if (!part)
++                      goto error_close_dev;
 +
++        PDEBUG;
 +
-+/*
-+ *
-+ */
-+static void 
-+fdasd_error(fdasd_anchor_t *anc,
-+          enum fdasd_failure why,
-+          char * str) 
-+{
-+PDEBUG
-+        char    error[2*LINE_LENGTH], *message = error;
++              part->num = i;
++              part->fs_type = ped_file_system_probe (&part->geom);
 +
-+      switch (why) 
-+      {
-+        case unable_to_open_disk:
-+              sprintf(error, _("%s open error\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case unable_to_seek_disk:
-+              sprintf(error, _("%s seek error\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case unable_to_read_disk:
-+              sprintf(error, _("%s read error\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case read_only_disk:
-+              sprintf(error, _("%s write error\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case unable_to_ioctl:
-+              sprintf(error, _("%s IOCTL error\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case api_version_mismatch:
-+                sprintf(error, _("%s API version mismatch\n%s\n"),
-+                        FDASD_ERROR, str);
-+                break;     
-+        case wrong_disk_type:
-+                sprintf(error, _("%s Unsupported disk type\n%s\n"),
-+                        FDASD_ERROR, str);
-+                break;           
-+        case wrong_disk_format:
-+                sprintf(error, _("%s Unsupported disk format\n%s\n"),
-+                        FDASD_ERROR, str);
-+                break;   
-+        case disk_in_use:
-+                sprintf(error, _("%s Disk in use\n%s\n"),
-+                        FDASD_ERROR, str);
-+                break;      
-+        case config_syntax_error:
-+                sprintf(error, _("%s Config file syntax error\n%s\n"),
-+                        FDASD_ERROR, str);
-+                break;       
-+        case vlabel_corrupted:
-+              sprintf(error, _("%s Volume label is corrupted.\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case dsname_corrupted:
-+              sprintf(error, _("%s a data set name is corrupted.\n%s\n"), 
-+                      FDASD_ERROR, str);
-+              break;
-+        case malloc_failed:
-+              sprintf(error, _("%s space allocation\n%s\n"),
-+                      FDASD_ERROR, str);
-+              break;
-+        case device_verification_failed:
-+              sprintf(error, _("%s device verification failed\n" \
-+                      "The specified device is not a valid DASD device\n"),
-+                      FDASD_ERROR);
-+              break;
-+      default: 
-+              sprintf(error, _("%s Fatal error\n%s\n"),
-+                      FDASD_ERROR, str);
-+      }
++                vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++                ch = strstr(p->f1->DS1DSNAM, "PART");
++                if (ch != NULL) {
++                        strncpy(str, ch+9, 6);
++                        str[6] = '\0';
++                        /*fprintf(stderr, "f1 label contains: >%s<\n", p->f1->DS1DSNAM);
++                } else {
++                        strcpy(str, "error");
++                        fprintf(stderr, "Error, f1 label contains: >%s<\n", p->f1->DS1DSNAM);
++                      */
++                }
 +
-+        ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, message);
-+}
++                dasd_data = part->disk_specific;
 +
++                if(strncmp(PART_TYPE_RAID, str, 6) == 0)
++                      ped_partition_set_flag(part, PED_PARTITION_RAID, 1);
++                else
++                      ped_partition_set_flag(part, PED_PARTITION_RAID, 0);
 +
-+/*
-+ * converts cyl-cyl-head-head-blk to blk
-+ */
-+static unsigned long 
-+cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo) 
-+{
-+PDEBUG
-+        return (unsigned long) (p->cc * geo->heads * geo->sectors + 
-+                                p->hh * geo->sectors +
-+                                p->b);
-+}
++                if(strncmp(PART_TYPE_LVM, str, 6) == 0)
++                      ped_partition_set_flag(part, PED_PARTITION_LVM, 1);
++                else
++                      ped_partition_set_flag(part, PED_PARTITION_LVM, 0);
 +
++                if(strncmp(PART_TYPE_SWAP, str, 6) == 0) {
++                        dasd_data->system = PARTITION_LINUX_SWAP;
++                        PDEBUG;
++                }
 +
-+/*
-+ *
-+ */
-+static char *fdasd_partition_type (char *str) 
-+{
-+PDEBUG
-+      if (strncmp("NATIVE", str, 6) == 0)
-+              strcpy(str, "Linux native");
-+      else if (strncmp("NEW   ", str, 6) == 0)
-+              strcpy(str, "Linux native");
-+      else if (strncmp("SWAP  ", str, 6) == 0)
-+              strcpy(str, "Linux swap");
-+      else if (strncmp("RAID  ", str, 6) == 0)
-+              strcpy(str, "Linux Raid");
-+      else
-+              strcpy(str, "unknown");
++                vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
 +
-+      return str;
-+}
++                dasd_data->part_info = (void *) p;
++                dasd_data->type = 0;
 +
++              constraint_exact = ped_constraint_exact (&part->geom);
++                if(!constraint_exact) 
++                        goto error_close_dev;
++              if (!ped_disk_add_partition (disk, part, constraint_exact))
++                      goto error_close_dev;
++              ped_constraint_destroy (constraint_exact);
 +
-+/*
-+ * initializes the anchor structure and allocates some
-+ * memory for the labels
-+ */
-+void
-+fdasd_initialize_anchor (fdasd_anchor_t * anc) 
-+{
-+PDEBUG
-+        int i;
-+      volume_label_t  *v;
-+      partition_info_t *p = NULL;
-+      partition_info_t *q = NULL;
++                if (p->fspace_trk > 0) {
++                        start = (long long)((long long) p->end_trk + 1)
++                                * (long long) disk->dev->hw_geom.sectors 
++                                * (long long) disk_specific->real_sector_size
++                                / (long long) disk->dev->sector_size
++                                ;
++                        end   = (long long)((long long) p->end_trk + 1 + p->fspace_trk) 
++                                * (long long) disk->dev->hw_geom.sectors
++                                * (long long) disk_specific->real_sector_size 
++                                / (long long) disk->dev->sector_size 
++                                - 1;
++                        part = ped_partition_new (disk, 0, NULL, start, end);
++                        if (!part)
++                                goto error_close_dev;
++                        part->type = PED_PARTITION_FREESPACE;
++                        constraint_exact = ped_constraint_exact (&part->geom);
++                        if(!constraint_exact) 
++                                goto error_close_dev;
++                        if (!ped_disk_add_partition (disk, part, constraint_exact))
++                                goto error_close_dev;
++                        ped_constraint_destroy (constraint_exact);
++                }
 +
-+      anc->devno             = 0;
-+      anc->dev_type          = 0;
-+      anc->used_partitions   = 0;
++              p = p->next;
++      }
 +
-+      anc->silent            = 0;
-+      anc->verbose           = 0;
-+      anc->big_disk          = 0;
-+      anc->volid_specified   = 0;
-+      anc->config_specified  = 0;
-+      anc->auto_partition    = 0;
-+      anc->devname_specified = 0;
-+      anc->print_table       = 0;
++        PDEBUG;
++      return 1;
 +
-+      anc->option_reuse      = 0;
-+      anc->option_recreate   = 0;
++error_close_dev:
++        PDEBUG;
++      return 0;
++}
 +
-+        anc->vlabel_changed    = 0;
-+      anc->vtoc_changed      = 0;
-+      anc->blksize           = 0;
-+      anc->fspace_trk        = 0;
-+      anc->label_pos         = 0;
++static int
++dasd_update_type(PedDisk* disk)
++{
++      PedPartition*           part;
++        LinuxSpecific*        arch_specific;
++        DasdDiskSpecific* disk_specific;
++        char *sys = NULL;
 +
-+      for (i=0; i<USABLE_PARTITIONS; i++)
-+              setpos(anc, i, -1);
++      arch_specific = LINUX_SPECIFIC (disk->dev);
++        disk_specific = disk->disk_specific;
 +
-+      bzero(anc->confdata, sizeof(config_data_t));
++        PDEBUG;
 +
-+      anc->f4 = malloc(sizeof(format4_label_t));
-+      if (anc->f4 == NULL) 
-+              fdasd_error(anc, malloc_failed, 
-+                          "FMT4 DSCB memory allocation failed.");
++      for (part = ped_disk_next_partition (disk, NULL); part;
++           part = ped_disk_next_partition (disk, part)) {
++                partition_info_t *p;
++                char *ch = NULL;
++                DasdPartitionData*            dasd_data;
 +
-+      anc->f5 = malloc(sizeof(format5_label_t));
-+      if (anc->f5 == NULL) 
-+              fdasd_error(anc, malloc_failed,
-+                          "FMT5 DSCB memory allocation failed.");
++                PDEBUG;
 +
-+      anc->f7 = malloc(sizeof(format7_label_t));
-+      if (anc->f7 == NULL) 
-+              fdasd_error(anc, malloc_failed,
-+                          "FMT7 DSCB memory allocation failed.");
++                if(part->type & PED_PARTITION_FREESPACE
++                   || part->type & PED_PARTITION_METADATA) {
++                        continue;
++                }
 +
-+      bzero(anc->f4, sizeof(format4_label_t));
-+      bzero(anc->f5, sizeof(format5_label_t));
-+      bzero(anc->f7, sizeof(format7_label_t));
++                PDEBUG;
 +
-+      v = malloc(sizeof(volume_label_t));
-+      if (v == NULL) 
-+              fdasd_error(anc, malloc_failed,
-+                          "Volume label memory allocation failed.");
-+      bzero(v, sizeof(volume_label_t));
-+      anc->vlabel = v;
++                dasd_data = part->disk_specific;
++                p = dasd_data->part_info;
++                if (!p ) {
++                        PDEBUG;
++                        continue;
++                }
++                vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++                ch = strstr(p->f1->DS1DSNAM, "PART");
++                /*fprintf(stderr, "f1 label contains: >%s<\n", p->f1->DS1DSNAM);*/
 +
-+      for (i=1; i<=USABLE_PARTITIONS; i++) 
-+      {
-+              p = malloc(sizeof(partition_info_t));
-+              if (p == NULL) 
-+                      fdasd_error(anc, malloc_failed,
-+                                 "Partition info memory allocation failed.");
-+              p->used       = 0x00;
-+              p->len_trk    = 0;
-+              p->start_trk  = 0;
-+              p->fspace_trk = 0;
-+              p->type       = 0;
++                PDEBUG;
++                if (ch == NULL) {
++                        vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++                        PDEBUG;
++                        continue;
++                }
 +
-+              /* add p to double pointered list */
-+              if (i == 1) 
-+              {
-+                      anc->first = p;
-+                      p->prev = NULL;
-+              } 
-+              else if (i == USABLE_PARTITIONS) 
-+              {
-+                      anc->last = p;
-+                      p->next = NULL;
-+                      p->prev = q;
-+                      q->next = p;
-+              } 
-+              else 
-+              {
-+                      p->prev = q;
-+                      q->next = p;
-+              }
++                ch += 9;
++                                
++                switch(dasd_data->system) {
++                case PARTITION_LINUX_LVM:
++                        PDEBUG;
++                        strncpy(ch, PART_TYPE_LVM, 6);
++                        break;
++                case PARTITION_LINUX_RAID:
++                        PDEBUG;
++                        strncpy(ch, PART_TYPE_RAID, 6);
++                        break;
++                case PARTITION_LINUX:
++                        PDEBUG;
++                        strncpy(ch, PART_TYPE_NATIVE, 6);
++                        break;
++                case PARTITION_LINUX_SWAP:
++                        PDEBUG;
++                        strncpy(ch, PART_TYPE_SWAP, 6);
++                        break;
++                default:
++                        PDEBUG;
++                        strncpy(ch, PART_TYPE_NATIVE, 6);
++                        break;
++                }
++                disk_specific->anchor->vtoc_changed++;
 +
-+              p->f1 = malloc(sizeof(format1_label_t));
-+              if (p->f1 == NULL) 
-+                      fdasd_error(anc, malloc_failed,
-+                          "FMT1 DSCB memory allocation failed.");
-+              bzero(p->f1, sizeof(format1_label_t));
-+              
-+              q = p;
-+      }
++                vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++        }
++        return 1;
 +}
-+
-+
-+/*
-+ * call IOCTL to re-read the partition table
-+ */
-+static void
-+fdasd_reread_partition_table (fdasd_anchor_t * anc, int fd)
++        
++static int
++dasd_write (PedDisk* disk)
 +{
-+PDEBUG
-+      char str[LINE_LENGTH];
-+      int f;
++      DasdPartitionData*      dasd_data;
++      PedPartition*           part;
++      int                     i;
++        int ret;
++      partition_info_t *p;
++        LinuxSpecific*        arch_specific;
++        DasdDiskSpecific* disk_specific;
++      PED_ASSERT (disk != NULL, return 0);
++      PED_ASSERT (disk->dev != NULL, return 0);
 +
-+      if (ioctl (fd, BLKRRPART, NULL) != 0)
-+              fdasd_error (anc, unable_to_ioctl, "Error while rereading "
-+                              "partition table.\nPlease reboot!");
-+}
++      arch_specific = LINUX_SPECIFIC (disk->dev);
++        disk_specific = disk->disk_specific;
 +
++        PDEBUG;
 +
-+/*
-+ * writes all changes to dasd
-+ */
-+static void
-+fdasd_write_vtoc_labels (fdasd_anchor_t * anc, int fd)
-+{ 
-+PDEBUG
-+      partition_info_t *p;
-+      unsigned long b;
-+      char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
-+      int i = 0, k = 0;
-+    
-+      b = (cchhb2blk (&anc->vlabel->vtoc, &anc->geo) - 1) * anc->blksize;
-+      if (b <= 0)
-+              fdasd_error (anc, vlabel_corrupted, "");
++      /* If formated in LDL, don't write anything. */
++      if (disk_specific->format_type == 1)
++              return 1;
 +
-+      /* write FMT4 DSCB */
-+      vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL);
++        /* XXX re-initialize anchor? */
++        fdasd_initialize_anchor(disk_specific->anchor);
++        fdasd_get_geometry(disk_specific->anchor, arch_specific->fd);
 +
-+      /* write FMT5 DSCB */
-+      b += anc->blksize;
-+      vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL);
++      /* check dasd for labels and vtoc */
++        if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd))
++              goto error;
 +
-+      /* write FMT7 DSCB */
-+      if (anc->big_disk)
-+      {
-+              b += anc->blksize;
-+              vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7);
-+      }
++      if ((disk_specific->anchor->geo.cylinders * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE)
++              disk_specific->anchor->big_disk++;
 +
-+      /* loop over all FMT1 DSCBs */
-+      p = anc->first;
-+      for (i = 0; i < USABLE_PARTITIONS; i++)
-+      {
-+              b += anc->blksize;
++        fdasd_recreate_vtoc(disk_specific->anchor);
 +
-+              if (p->used != 0x01)
-+              {
-+                      vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
++      for (i = 1; i <= USABLE_PARTITIONS; i++) {
++                unsigned int start, stop;
++                int type;
++
++                PDEBUG;
++              part = ped_disk_get_partition (disk, i);
++              if (!part)
 +                      continue;
-+              }
-+  
-+              strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
 +
-+              ch = p->f1->DS1DSNAM;
-+              vtoc_ebcdic_dec (ch, ch, 44);
-+              c1 = ch + 7;
-+  
-+              if (getdsn (anc, i) > -1)
-+              {
-+                      /* re-use the existing data set name */
-+                      c2 = strchr (c1, '.');
-+                      if (c2 != NULL)
-+                              strncpy (s2, c2, 31);
-+                      else
-+                              fdasd_error (anc, dsname_corrupted, "");
++                PDEBUG;
 +
-+                      strncpy (s1, anc->vlabel->volid, 6);
-+                      vtoc_ebcdic_dec (s1, s1, 6);
-+                      s1[6] = ' ';
-+                      strncpy (c1, s1, 7);
-+                      c1 = strchr (ch, ' ');
-+                      strncpy (c1, s2, 31);
-+              }
-+              else
-+              {
-+                      /* create a new data set name */
-+                      while (getpos (anc, k) > -1)
-+                              k++;
++                start = part->geom.start * disk->dev->sector_size 
++                        / disk_specific->real_sector_size / disk->dev->hw_geom.sectors;
++                stop = (part->geom.end + 1) 
++                        * disk->dev->sector_size / disk_specific->real_sector_size
++                        / disk->dev->hw_geom.sectors - 1;
 +
-+                      setpos (anc, k, i);
++                PDEBUG;
++                dasd_data = part->disk_specific;
++                
++                type = dasd_data->type;
++                PDEBUG;
++                /*fprintf(stderr, "Partition %d  %ld - %ld \t", i, part->geom.start, part->geom.end);
++                fprintf(stderr, "Partition %d  %ld - %ld \n", i, start, stop);
++              */
 +
-+                      strncpy (s2, ch, 44);
-+                      s2[44] = 0;
-+                      vtoc_ebcdic_dec (s2, s2, 44);
++                p = fdasd_add_partition(disk_specific->anchor, start, stop);
++                if(!p) {
++                        PDEBUG;
++                        return 0;
++                }
++                dasd_data->part_info = (void *) p;
++              p->type = dasd_data->system;
++      }
++        PDEBUG;
 +
-+                      strncpy (ch, "LINUX.V               " "                      ", 44);
++        if(!fdasd_prepare_labels(disk_specific->anchor, arch_specific->fd))
++                return 0;
 +
-+                      strncpy (s1, anc->vlabel->volid, 6);
-+                      vtoc_ebcdic_dec (s1, s1, 6);
-+                      strncpy (c1, s1, 6);
++        dasd_update_type(disk);
++        PDEBUG;
 +
-+                      c1 = strchr (ch, ' ');
-+                      strncpy (c1, ".PART", 5);
-+                      c1 += 5;
++        if(!fdasd_write_labels(disk_specific->anchor, arch_specific->fd))
++                return 0;
 +
-+                      sprintf (dsno, "%04d.", k + 1);
-+                      strncpy (c1, dsno, 5);
++        return 1;
++ error:
++        PDEBUG;
++      return 0;
++}
 +
-+                      c1 += 5;
-+                      switch(p->type) {
-+                              case PARTITION_LINUX_LVM:
-+                                      strncpy(c1, PART_TYPE_LVM, 6);
-+                                      break;
-+                              case PARTITION_LINUX_RAID:
-+                                      strncpy(c1, PART_TYPE_RAID, 6);
-+                                      break;
-+                              case PARTITION_LINUX:
-+                                      strncpy(c1, PART_TYPE_NATIVE, 6);
-+                                      break;
-+                              case PARTITION_LINUX_SWAP:
-+                                      strncpy(c1, PART_TYPE_SWAP, 6);
-+                                      break;
-+                              default:
-+                                      strncpy(c1, PART_TYPE_NATIVE, 6);
-+                                      break;
-+                      }
-+              }
-+              vtoc_ebcdic_enc (ch, ch, 44);
++static PedPartition*
++dasd_partition_new (const PedDisk* disk, PedPartitionType part_type,
++                 const PedFileSystemType* fs_type,
++                 PedSector start, PedSector end)
++{
++      PedPartition*           part;
 +
-+              vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
-+              p = p->next;
-+      }
++      part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
++      if (!part)
++              goto error;
++
++        part->disk_specific = ped_malloc (sizeof (DasdPartitionData));
++      return part;
++
++error:
++      return 0;
 +}
 +
 +
-+/*
-+ * writes all changes to dasd
-+ */
-+int
-+fdasd_write_labels (fdasd_anchor_t * anc, int fd)
++static void
++dasd_partition_destroy (PedPartition* part)
 +{
-+PDEBUG
-+      if (anc->vlabel_changed)
-+      {
-+              vtoc_write_volume_label (fd, anc->label_pos, anc->vlabel);
-+      }
++      PED_ASSERT (part != NULL, return);
 +
-+      if (anc->vtoc_changed)
-+              fdasd_write_vtoc_labels (anc, fd);
++      if (ped_partition_is_active (part))
++              ped_free (part->disk_specific);
++      ped_free (part);
++}
 +
-+      /*
-+      if ((anc->vtoc_changed) || (anc->vlabel_changed))
-+              fdasd_reread_partition_table (anc, fd);
 +
-+      */
++static int
++dasd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
++{
++      PedDisk*                        disk;
++      PedPartition*                   walk;
++      DasdPartitionData*              dasd_data;
++      const PedFileSystemType*        fs_type;
 +
-+      return 1;
++      PED_ASSERT (part != NULL, return 0);
++      PED_ASSERT (part->disk_specific != NULL, return 0);
++      dasd_data = part->disk_specific;
++
++      switch (flag) {
++      case PED_PARTITION_RAID:
++              if (state) {
++                      dasd_data->lvm = 0;
++              }
++              dasd_data->raid = state;
++              return ped_partition_set_system (part, part->fs_type);
++      case PED_PARTITION_LVM:
++              if (state) {
++                      dasd_data->raid = 0;
++              }
++              dasd_data->lvm = state;
++              return ped_partition_set_system (part, part->fs_type);
++      default:
++              return 0;
++      }
 +}
 +
 +
-+/*
-+ * writes all changes to dasd
-+ */
-+int
-+fdasd_prepare_labels (fdasd_anchor_t *anc, int fd) 
++static int
++dasd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
 +{
-+PDEBUG
-+        partition_info_t *p = anc->first;
-+      char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
-+      int i = 0, k = 0;
++      DasdPartitionData*      dasd_data;
 +
-+      /* loop over all FMT1 DSCBs */
-+      p = anc->first;
-+      for (i = 0; i < USABLE_PARTITIONS; i++)
-+      {
-+              strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
++      PED_ASSERT (part != NULL, return 0);
++      PED_ASSERT (part->disk_specific != NULL, return 0);
++      dasd_data = part->disk_specific;
 +
-+              ch = p->f1->DS1DSNAM;
-+              vtoc_ebcdic_dec (ch, ch, 44);
-+              c1 = ch + 7;
-+  
-+              if (getdsn (anc, i) > -1)
-+              {
-+                      /* re-use the existing data set name */
-+                      c2 = strchr (c1, '.');
-+                      if (c2 != NULL)
-+                              strncpy (s2, c2, 31);
-+                      else
-+                              fdasd_error (anc, dsname_corrupted, "");
++      switch (flag) {
++      case PED_PARTITION_RAID:
++              return dasd_data->raid;
 +
-+                      strncpy (s1, anc->vlabel->volid, 6);
-+                      vtoc_ebcdic_dec (s1, s1, 6);
-+                      s1[6] = ' ';
-+                      strncpy (c1, s1, 7);
-+                      c1 = strchr (ch, ' ');
-+                      strncpy (c1, s2, 31);
-+              }
-+              else
-+              {
-+                      /* create a new data set name */
-+                      while (getpos (anc, k) > -1)
-+                              k++;
++      case PED_PARTITION_LVM:
++              return dasd_data->lvm;
 +
-+                      setpos (anc, k, i);
++      default:
++              return 0;
++      }
++}
 +
-+                      strncpy (s2, ch, 44);
-+                      s2[44] = 0;
-+                      vtoc_ebcdic_dec (s2, s2, 44);
++static int
++dasd_partition_is_flag_available (const PedPartition* part,
++                               PedPartitionFlag flag)
++{
++      switch (flag) {
++      case PED_PARTITION_RAID:
++              return 1;
 +
-+                      strncpy (ch, "LINUX.V               " "                      ", 44);
++      case PED_PARTITION_LVM:
++              return 1;
 +
-+                      strncpy (s1, anc->vlabel->volid, 6);
-+                      vtoc_ebcdic_dec (s1, s1, 6);
-+                      strncpy (c1, s1, 6);
++      default:
++              return 0;
++      }
++}
 +
-+                      c1 = strchr (ch, ' ');
-+                      strncpy (c1, ".PART", 5);
-+                      c1 += 5;
 +
-+                      sprintf (dsno, "%04d.", k + 1);
-+                      strncpy (c1, dsno, 5);
++static int
++dasd_get_max_primary_partition_count (const PedDisk* disk)
++{
++        DasdDiskSpecific* disk_specific;
 +
-+                      c1 += 5;
-+                      switch(p->type) {
-+                              case PARTITION_LINUX_LVM:
-+                                      strncpy(c1, PART_TYPE_LVM, 6);
-+                                      break;
-+                              case PARTITION_LINUX_RAID:
-+                                      strncpy(c1, PART_TYPE_RAID, 6);
-+                                      break;
-+                              case PARTITION_LINUX:
-+                                      strncpy(c1, PART_TYPE_NATIVE, 6);
-+                                      break;
-+                              case PARTITION_LINUX_SWAP:
-+                                      strncpy(c1, PART_TYPE_SWAP, 6);
-+                                      break;
-+                              default:
-+                                      strncpy(c1, PART_TYPE_NATIVE, 6);
-+                                      break;
-+                      }
-+              }
-+              vtoc_ebcdic_enc (ch, ch, 44);
-+              p = p->next;
-+      }
-+      return 1;
-+}
++      disk_specific = disk->disk_specific;
++      /* If formated in LDL, maximum partition number is 1 */
++      if (disk_specific->format_type == 1)
++              return 1;
 +
++      return USABLE_PARTITIONS;
++}
 +
-+/*
-+ *
-+ */
-+void
-+fdasd_recreate_vtoc(fdasd_anchor_t *anc)
++static PedConstraint*
++_primary_constraint (PedDisk* disk)
 +{
-+PDEBUG
-+      partition_info_t *p = anc->first;
-+      int i;
-+
-+      vtoc_init_format4_label(anc->f4,
-+                              USABLE_PARTITIONS,
-+                              anc->geo.cylinders,
-+                              anc->geo.heads,
-+                              anc->geo.sectors,
-+                              anc->blksize,
-+                              anc->dev_type);
-+
-+      vtoc_init_format5_label(anc->f5);
-+      vtoc_init_format7_label(anc->f7);
-+      vtoc_set_freespace(anc->f4, anc->f5, anc->f7, 
-+                         '+', anc->verbose,
-+                         FIRST_USABLE_TRK,
-+                         anc->geo.cylinders * anc->geo.heads - 1,
-+                         anc->geo.cylinders, anc->geo.heads);
++      PedAlignment    start_align;
++      PedAlignment    end_align;
++      PedGeometry     max_geom;
++      PedSector       sector_size;
++        LinuxSpecific*  arch_specific;
++        DasdDiskSpecific* disk_specific;
 +
-+      for (i = 0; i < USABLE_PARTITIONS; i++)
-+      {
-+              bzero(p->f1, sizeof(format1_label_t));
-+              p->used       = 0x00;
-+              p->start_trk  = 0;
-+              p->end_trk    = 0;
-+              p->len_trk    = 0;
-+              p->fspace_trk = 0;
-+              p->type       = 0;
-+              p = p->next;
-+      }
++        PDEBUG;
 +
-+      anc->used_partitions = 0;
-+      anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
++        arch_specific = LINUX_SPECIFIC (disk->dev);
++        disk_specific = disk->disk_specific;
++      sector_size = disk_specific->real_sector_size / disk->dev->sector_size;
 +
-+      for (i=0; i<USABLE_PARTITIONS; i++)
-+              setpos(anc, i, -1);
++      if (!ped_alignment_init (&start_align, 0, disk->dev->hw_geom.sectors * sector_size))
++              return NULL;
++      if (!ped_alignment_init (&end_align, -1, disk->dev->hw_geom.sectors * sector_size))
++              return NULL;
++      if (!ped_geometry_init (&max_geom, disk->dev, 0, disk->dev->length))
++              return NULL;
 +
-+      anc->vtoc_changed++;
++      return ped_constraint_new (&start_align, &end_align, &max_geom,
++                                 &max_geom, 1, disk->dev->length);
 +}
 +
-+
-+/*
-+ * changes the volume serial
-+ */
-+static void
-+fdasd_change_volser (fdasd_anchor_t *anc, char *line_ptr) 
++static int
++dasd_partition_align (PedPartition* part, const PedConstraint* constraint)
 +{
-+PDEBUG
-+      char str[10];
-+
-+        if (strcmp(line_ptr, "") != 0) 
-+      {
-+              int i;
-+
-+              /* fill with blanks if necessary and remove the linebreak */
-+              i = strlen(line_ptr);
-+              if (i <= 6)
-+              {
-+                      strncpy(line_ptr + i - 1, "      ", 6);
-+              }
++        DasdDiskSpecific* disk_specific;
 +
-+              strncpy(str, line_ptr, 6);
++      PED_ASSERT (part != NULL, return 0);
 +
-+              for (i=0; i<6; i++) str[i] = toupper(str[i]);
-+              str[6] = 0x00;
++      disk_specific = part->disk->disk_specific;
++      /* If formated in LDL, ignore metadata partition */
++      if (disk_specific->format_type == 1)
++              return 1;
 +
-+              fdasd_check_volser (str, anc->devno);
-+              vtoc_volume_label_set_volser(anc->vlabel, str);
++      if (_ped_partition_attempt_align (part, constraint,
++                                        _primary_constraint (part->disk)))
++              return 1;
 +
-+              vtoc_set_cchhb(&anc->vlabel->vtoc, 0x0000, 0x0001, 0x01);
-+              anc->vlabel_changed++;
-+              anc->vtoc_changed++;
-+      }
++#ifndef DISCOVER_ONLY
++      ped_exception_throw (
++              PED_EXCEPTION_ERROR,
++              PED_EXCEPTION_CANCEL,
++              _("Unable to satisfy all constraints on the partition."));
++#endif
++      return 0;
 +}
 +
 +
-+/*
-+ * sets some important partition data
-+ * (like used, start_trk, end_trk, len_trk)
-+ * by calculating these values with the
-+ * information provided in the labels
-+ */
-+static void
-+fdasd_update_partition_info (fdasd_anchor_t *anc) 
++static int
++dasd_partition_enumerate (PedPartition* part)
 +{
-+PDEBUG
-+      partition_info_t *q = NULL, *p = anc->first;
-+      unsigned int h = anc->geo.heads;
-+      unsigned long max = anc->geo.cylinders * h - 1;
 +      int i;
-+      char *ch;
-+
-+      anc->used_partitions = anc->geo.sectors - 2 - anc->f4->DS4DSREC;
-+
-+      for (i = 1; i <= USABLE_PARTITIONS; i++)
-+      {
-+              if (p->f1->DS1FMTID != 0xf1)
-+              {
-+                      if (i == 1)
-+                              /* there is no partition at all */
-+                              anc->fspace_trk = max - FIRST_USABLE_TRK + 1;
-+                      else
-+                              /* previous partition was the last one */
-+                              q->fspace_trk = max - q->end_trk;
-+                      break;
++      PedPartition* p;
++      
++      /* never change the partition numbers */
++      if (part->num != -1)
++              return 1;
++      for (i = 1; i <= USABLE_PARTITIONS; i++) {
++              p = ped_disk_get_partition (part->disk, i);
++              if (!p) {
++                      part->num = i;
++                      return 1;
 +              }
++      }
 +
-+              /* this is a valid format 1 label */
-+              p->used = 0x01;
-+              p->start_trk = p->f1->DS1EXT1.llimit.cc * h +
-+                             p->f1->DS1EXT1.llimit.hh;
-+              p->end_trk   = p->f1->DS1EXT1.ulimit.cc * h +
-+                             p->f1->DS1EXT1.ulimit.hh;
-+              p->len_trk   = p->end_trk - p->start_trk + 1;
++      /* failed to allocate a number */
++      ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
++                           _("Unable to allocate a dasd disklabel slot"));
++      return 0;
++}
 +
-+              if (i == 1)
-+                      /* first partition, there is at least one */
-+                      anc->fspace_trk = p->start_trk - FIRST_USABLE_TRK;
-+              else
-+              {
-+                      if (i == USABLE_PARTITIONS)
-+                              /* last possible partition */
-+                              p->fspace_trk = max - p->end_trk;
++static int
++dasd_partition_set_system (PedPartition* part,
++                          const PedFileSystemType* fs_type)
++{
++      DasdPartitionData* dasd_data = part->disk_specific;
++      PedSector cyl_size = part->disk->dev->hw_geom.sectors * part->disk->dev->hw_geom.heads;
 +
-+                      /* set free space values of previous partition */
-+                      q->fspace_trk = p->start_trk - q->end_trk - 1;
-+              }
++        PDEBUG;
 +
-+              ch = p->f1->DS1DSNAM;
-+              vtoc_ebcdic_dec (ch, ch, 44);
-+              if (strstr(ch, PART_TYPE_LVM))
-+                      p->type = PARTITION_LINUX_LVM;
-+              else if (strstr(ch, PART_TYPE_RAID))
-+                      p->type = PARTITION_LINUX_RAID;
-+              else if (strstr(ch, PART_TYPE_NATIVE))
-+                      p->type = PARTITION_LINUX;
-+              else if (strstr(ch, PART_TYPE_SWAP))
-+                      p->type = PARTITION_LINUX_SWAP;
-+              else
-+                      p->type = PARTITION_LINUX;
-+              vtoc_ebcdic_enc (ch, ch, 44);
++      part->fs_type = fs_type;
 +
-+              q = p;
-+              p = p->next;
++      if (dasd_data->lvm) {
++              dasd_data->system = PARTITION_LINUX_LVM;
++        PDEBUG;
++              return 1;
 +      }
-+}
++      if (dasd_data->raid) {
++              dasd_data->system = PARTITION_LINUX_RAID;
++        PDEBUG;
++              return 1;
++      }
++      if (!fs_type) {
++              dasd_data->system = PARTITION_LINUX;
++        PDEBUG;
++      } else if (!strcmp (fs_type->name, "linux-swap")) {
++              dasd_data->system = PARTITION_LINUX_SWAP;
++        PDEBUG;
++        } else {
++              dasd_data->system = PARTITION_LINUX;
++        PDEBUG;
++        }
 +
++      return 1;
++}
 +
-+/*
-+ * reorganizes all FMT1s, after that all used FMT1s should be right in 
-+ * front of all unused FMT1s
-+ */
-+static void
-+fdasd_reorganize_FMT1s (fdasd_anchor_t *anc) 
++static int
++dasd_alloc_metadata (PedDisk* disk)
 +{
-+PDEBUG
-+      int i, j;
-+      format1_label_t *ltmp;
-+      partition_info_t *ptmp;
++      PedPartition*           new_part;
++      PedConstraint*          constraint_any = NULL;
++        PedSector             vtoc_end;
++        LinuxSpecific*                arch_specific;
++        DasdDiskSpecific*     disk_specific;
 +
-+      for (i=1; i<=USABLE_PARTITIONS - 1; i++)
-+      {
-+              ptmp = anc->first;
-+              for (j=1; j<=USABLE_PARTITIONS - i; j++)
-+              {
-+                      if (ptmp->f1->DS1FMTID < ptmp->next->f1->DS1FMTID)
-+                      {
-+                              ltmp = ptmp->f1;
-+                              ptmp->f1 = ptmp->next->f1;
-+                              ptmp->next->f1 = ltmp;
-+                      }
-+                      ptmp=ptmp->next;
-+              }
-+      }
-+}
++      PED_ASSERT (disk != NULL, goto error);
++      PED_ASSERT (disk->dev != NULL, goto error);
++
++      arch_specific = LINUX_SPECIFIC (disk->dev);
++        disk_specific = disk->disk_specific;
++
++      constraint_any = ped_constraint_any (disk->dev);
++
++      /* If formated in LDL, the real partition starts at sector 24. */
++      if (disk_specific->format_type == 1)
++              vtoc_end = 23;
++        else
++        /* Mark the start of the disk as metadata. */
++              vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors 
++                              * (long long) disk_specific->real_sector_size
++                              / (long long) disk->dev->sector_size) - 1;
++      new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
++                                      0, vtoc_end);
++      if (!new_part)
++              goto error;
 +
++      if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
++              ped_partition_destroy (new_part);
++              goto error;
++      }
 +
++      ped_constraint_destroy (constraint_any);
++      return 1;
++error:
++      ped_constraint_destroy (constraint_any);
++      return 0;
++}
+diff -urN parted-1.7.0.orig/libparted/labels/fdasd.c parted-1.7.0/libparted/labels/fdasd.c
+--- parted-1.7.0.orig/libparted/labels/fdasd.c 1969-12-31 19:00:00.000000000 -0500
++++ parted-1.7.0/libparted/labels/fdasd.c      2006-05-19 14:37:55.000000000 -0400
+@@ -0,0 +1,1302 @@
 +/*
++ * File...........: arch/s390/tools/fdasd.c
++ * Author(s)......: Volker Sameske <sameske@de.ibm.com>
++ * Bugreports.to..: <Linux390@de.ibm.com>
++ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2001
 + *
++ * History of changes (starts March 2001)
++ * 2001-04-11 possibility to change volume serial added
++ *            possibility to change partition type added
++ *            some changes to DS4HPCHR and DS4DSREC
++ * 2001-05-03 check for invalid partition numbers added
++ *            wrong free_space calculation bug fixed
++ * 2001-06-26 '-a' option added, it is now possible to add a single
++ *            partition in non-interactive mode
++ * 2001-06-26 long parameter support added
++ *           
 + */
-+static void
-+fdasd_process_valid_vtoc (fdasd_anchor_t * anc, unsigned long b, int fd)
-+{
-+PDEBUG
-+      int f5_counter = 0, f7_counter = 0, f1_counter = 0, oldfmt = 0;
-+      int i, n, f1size = sizeof (format1_label_t);
-+      partition_info_t *p = anc->first;
-+      format1_label_t q;
-+      char s[5], *ch;
-+
-+      b += anc->blksize;
-+
-+      for (i = 1; i <= anc->geo.sectors; i++)
-+      {
-+              bzero (&q, f1size);
-+              vtoc_read_label (fd, b, &q, NULL, NULL, NULL);
++#include <parted/vtoc.h>
++#include <parted/fdasd.h>
 +
-+              switch (q.DS1FMTID)
-+              {
-+                      case 0xf1:
-+                              if (p == NULL)
-+                                      break;
-+                              memcpy (p->f1, &q, f1size);
++#include <parted/parted.h>
 +
-+                              n = -1;
-+                              vtoc_ebcdic_dec (p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
-+                              ch = strstr (p->f1->DS1DSNAM, "PART");
-+                              if (ch != NULL)
-+                              {
-+                                      strncpy (s, ch + 4, 4);
-+                                      s[4] = '\0';
-+                                      n = atoi (s) - 1;
-+                              }
++#include <libintl.h>
++#if ENABLE_NLS
++#  define _(String) dgettext (PACKAGE, String)
++#else
++#  define _(String) (String)
++#endif /* ENABLE_NLS */
 +
-+                              vtoc_ebcdic_enc (p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
 +
-+                              /* this dasd has data set names 0000-0002
-+                              but we use now 0001-0003 */
-+                              if (n == -1)
-+                                      oldfmt++;
++#define GETARG(x) {int k=strlen(optarg);x=malloc(k);strncpy(x,optarg,k);}
 +
-+                              if (((oldfmt == 0) && (n < 0)) || (n >= USABLE_PARTITIONS))
-+                              {
-+                              }
-+                              else
-+                              {
-+                                      if (oldfmt)       /* correct +1 */
-+                                      {
-+                                              setpos (anc, n + 1, f1_counter);
-+                                      }
-+                                      else
-+                                              setpos (anc, n, f1_counter);
-+                              }
++static int
++getpos (fdasd_anchor_t *anc, int dsn)
++{
++PDEBUG
++      return anc->partno[dsn];
++}
 +
-+                              p = p->next;
-+                              f1_counter++;
-+                              break;
-+                      case 0xf5:
-+                              memcpy (anc->f5, &q, f1size);
-+                              f5_counter++;
-+                              break;
-+                      case 0xf7:
-+                              if (f7_counter == 0)
-+                                      memcpy (anc->f7, &q, f1size);
-+                              f7_counter++;
-+                              break;
-+              }
-+              b += anc->blksize;
-+      }
++static int
++getdsn (fdasd_anchor_t *anc, int pos)
++{
++PDEBUG
++      int i;
 +
-+      if (oldfmt > 0)
++      for (i=0; i<USABLE_PARTITIONS; i++)
 +      {
-+              /* this is the old format PART0000 - PART0002 */
-+              anc->vtoc_changed++;
++              if (anc->partno[i] == pos)
++                      return i;
 +      }
 +
-+      if ((f5_counter == 0) || (anc->big_disk))
-+              vtoc_init_format5_label (anc->f5);
-+
-+      if (f7_counter == 0)
-+              vtoc_init_format7_label (anc->f7);
++      return -1;
++}
 +
-+      fdasd_reorganize_FMT1s (anc);
-+      fdasd_update_partition_info (anc);
++static void
++setpos (fdasd_anchor_t *anc, int dsn, int pos)
++{
++PDEBUG
++      anc->partno[dsn] = pos;
 +}
 +
 +
++static void
++fdasd_check_volser (char *s, int devno)
++{
++PDEBUG
++  int i, j;
++
++  for (i = 0; i < 6; i++)
++    {
++      if ((s[i] < 0x20) || (s[i] > 0x7a) || ((s[i] >= 0x21) && (s[i] <= 0x22)) ||      /* !"         */
++         ((s[i] >= 0x26) && (s[i] <= 0x2f)) || /* &'()*+,-./ */
++         ((s[i] >= 0x3a) && (s[i] <= 0x3f)) || /* :;<=>?     */
++         ((s[i] >= 0x5b) && (s[i] <= 0x60)))   /* \]^_´     */
++       s[i] = ' ';
++      s[i] = toupper (s[i]);
++    }
++  s[6] = 0x00;
++
++  for (i = 0; i < 6; i++)
++    {
++      if (s[i] == ' ')
++       for (j = i; j < 6; j++)
++         if (s[j] != ' ')
++           {
++             s[i] = s[j];
++             s[j] = ' ';
++             break;
++           }
++    }
++
++  if (s[0] == ' ')
++    {
++      printf ("Usage error, switching to default.\n");
++      sprintf (s, "0X%04x", devno);
++      for (i = 0; i < 6; i++)
++       s[i] = toupper (s[i]);
++    }
++}
++
 +/*
 + *
 + */
-+static int
-+fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd)
++void
++fdasd_cleanup (fdasd_anchor_t *anchor) 
 +{
 +PDEBUG
-+      char str[LINE_LENGTH];
++        int i;
++        partition_info_t *p, *q;
 +
-+      /* VOL1 label contains valid VTOC pointer */ 
-+      vtoc_read_label (fd, b, NULL, anc->f4, NULL, NULL);
++        if (anchor == NULL) return;
 +
-+      if (anc->f4->DS4IDFMT != 0xf4)
++      if (anchor->f4 != NULL) free(anchor->f4);
++      if (anchor->f5 != NULL) free(anchor->f5);
++      if (anchor->f7 != NULL) free(anchor->f7);
++      if (anchor->vlabel != NULL) free(anchor->vlabel);
++
++      p = anchor->first;
++      if (p == NULL)
++              return;
++
++        for (i=1; i <= USABLE_PARTITIONS; i++) 
 +      {
-+              if (strncmp (anc->vlabel->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
-+                      return 0;
-+              /* format4 DSCB is invalid
-+              printf(" invalid\ncreating new VTOC...\n"); */
-+              fdasd_error(anc, wrong_disk_format, "Invalid VTOC");
++              if (p == NULL)
++                      return;
++              q = p->next;
++              free(p);
++              p = q;
 +      }
-+      else
-+              fdasd_process_valid_vtoc (anc, b, fd);
-+
-+      return 0;
 +}
 +
 +
 +/*
-+ * check the dasd for a volume label
++ *
 + */
-+int 
-+fdasd_check_volume (fdasd_anchor_t *anc, int fd) 
++static void 
++fdasd_error(fdasd_anchor_t *anc,
++          enum fdasd_failure why,
++          char * str) 
 +{
 +PDEBUG
-+      volume_label_t *v = anc->vlabel;
-+      unsigned long b = -1;
-+      char str[LINE_LENGTH];
-+
-+      vtoc_read_volume_label (fd, anc->label_pos, v);
++        char    error[2*LINE_LENGTH], *message = error;
 +
-+      if (strncmp (v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0)
++      switch (why) 
 +      {
-+              /* found VOL1 volume label */
-+              b = (cchhb2blk (&v->vtoc, &anc->geo) - 1) * anc->blksize;
-+              if (b > 0)
-+              {
-+                      int rc;
-+                      rc = fdasd_valid_vtoc_pointer (anc, b, fd);
-+
-+                      if (rc < 0)
-+                              return 1;
-+                      else
-+                              return 0;
-+              }
-+              else 
-+              {
-+                      return 1;
-+              }
-+        }
-+      else if (strncmp (v->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
-+      {
-+              return 0;
++        case unable_to_open_disk:
++              sprintf(error, _("%s open error\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case unable_to_seek_disk:
++              sprintf(error, _("%s seek error\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case unable_to_read_disk:
++              sprintf(error, _("%s read error\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case read_only_disk:
++              sprintf(error, _("%s write error\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case unable_to_ioctl:
++              sprintf(error, _("%s IOCTL error\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case api_version_mismatch:
++                sprintf(error, _("%s API version mismatch\n%s\n"),
++                        FDASD_ERROR, str);
++                break;     
++        case wrong_disk_type:
++                sprintf(error, _("%s Unsupported disk type\n%s\n"),
++                        FDASD_ERROR, str);
++                break;           
++        case wrong_disk_format:
++                sprintf(error, _("%s Unsupported disk format\n%s\n"),
++                        FDASD_ERROR, str);
++                break;   
++        case disk_in_use:
++                sprintf(error, _("%s Disk in use\n%s\n"),
++                        FDASD_ERROR, str);
++                break;      
++        case config_syntax_error:
++                sprintf(error, _("%s Config file syntax error\n%s\n"),
++                        FDASD_ERROR, str);
++                break;       
++        case vlabel_corrupted:
++              sprintf(error, _("%s Volume label is corrupted.\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case dsname_corrupted:
++              sprintf(error, _("%s a data set name is corrupted.\n%s\n"), 
++                      FDASD_ERROR, str);
++              break;
++        case malloc_failed:
++              sprintf(error, _("%s space allocation\n%s\n"),
++                      FDASD_ERROR, str);
++              break;
++        case device_verification_failed:
++              sprintf(error, _("%s device verification failed\n" \
++                      "The specified device is not a valid DASD device\n"),
++                      FDASD_ERROR);
++              break;
++      default: 
++              sprintf(error, _("%s Fatal error\n%s\n"),
++                      FDASD_ERROR, str);
 +      }
 +
-+        return 1;
++        ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, message);
 +}
 +
 +
 +/*
-+ * checks the current API version with the API version of the dasd driver
++ * converts cyl-cyl-head-head-blk to blk
 + */
-+void
-+fdasd_check_api_version (fdasd_anchor_t *anc, int f)
++static unsigned long 
++cchhb2blk (cchhb_t *p, struct fdasd_hd_geometry *geo) 
 +{
 +PDEBUG
-+        int api;
-+      char s[LINE_LENGTH];
-+ 
-+        if (ioctl(f, DASDAPIVER, &api) != 0)
-+        {
-+                fdasd_error(anc, unable_to_ioctl,
-+                            "Could not retrieve API version.");
-+        }
-+ 
-+      if (api != DASD_MIN_API_VERSION)
-+      {
-+              sprintf(s, "The current API version '%d' doesn't " \
-+                      "match dasd driver API version " \
-+                      "'%d'!", api, DASD_MIN_API_VERSION);
-+              fdasd_error(anc, api_version_mismatch, s);
-+      }
-+}                                      
++        return (unsigned long) (p->cc * geo->heads * geo->sectors + 
++                                p->hh * geo->sectors +
++                                p->b);
++}
 +
 +
 +/*
-+ * reads dasd geometry data
++ *
 + */
-+void 
-+fdasd_get_geometry (fdasd_anchor_t *anc, int f) 
++static char *fdasd_partition_type (char *str) 
 +{
 +PDEBUG
-+        int blksize = 0;
-+      dasd_information_t dasd_info;
-+      char s[LINE_LENGTH];
-+
-+      if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0) 
-+      {
-+              fdasd_error(anc, unable_to_ioctl, 
-+                          "Could not retrieve disk geometry information.");
-+      }
-+
-+      if (ioctl(f, BLKSSZGET, &blksize) != 0)
-+      {
-+              fdasd_error(anc, unable_to_ioctl,
-+                          "Could not retrieve blocksize information.");
-+      }
-+
-+      /* get disk type */
-+      if (ioctl(f, BIODASDINFO, &dasd_info) != 0) 
-+      {
-+              fdasd_error(anc, unable_to_ioctl, 
-+                          "Could not retrieve disk information.");
-+      }
-+
-+      if (strncmp(dasd_info.type, "ECKD", 4) != 0)
-+      {
-+              sprintf(s, "This is not an ECKD disk! This disk type " \
-+                      "is not supported!");
-+              fdasd_error(anc,wrong_disk_type, s);
-+      }
-+
-+      /* Disable FBA_layout check
-+        if (dasd_info.FBA_layout)
-+        {
-+         if(!anc->silent) {
-+                sprintf(s, "Device is not formatted with z/OS compatible " \
-+                      "disk layout!");
-+                fdasd_error(anc,wrong_disk_format, s);
-+         }
-+        }      
-+      */
-+
-+      /* We do not write yet, so let this check go 
-+      if (dasd_info.open_count > 1)
-+      {
-+              sprintf(s, "Device is in use by another program. Exit all " \
-+                      "applications using this disk and/or unmount it.");
-+              fdasd_error(anc,disk_in_use, s);
-+      }
-+      */
++      if (strncmp("NATIVE", str, 6) == 0)
++              strcpy(str, "Linux native");
++      else if (strncmp("NEW   ", str, 6) == 0)
++              strcpy(str, "Linux native");
++      else if (strncmp("SWAP  ", str, 6) == 0)
++              strcpy(str, "Linux swap");
++      else if (strncmp("RAID  ", str, 6) == 0)
++              strcpy(str, "Linux Raid");
++      else
++              strcpy(str, "unknown");
 +
-+      anc->dev_type   = dasd_info.dev_type;
-+      anc->blksize    = blksize;
-+      anc->label_pos  = dasd_info.label_block * blksize;
-+      anc->devno      = dasd_info.devno;
-+      anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
++      return str;
 +}
 +
-+/*
-+ * returns unused partition info pointer if there
-+ * is a free partition, otherwise NULL
-+ */
-+static partition_info_t * 
-+fdasd_get_empty_f1_label (fdasd_anchor_t * anc) 
-+{
-+PDEBUG
-+      if (anc->used_partitions < USABLE_PARTITIONS)     
-+              return anc->last;             
-+      else
-+              return NULL;
-+}
 +
 +/*
-+ * asks for and sets some important partition data
++ * initializes the anchor structure and allocates some
++ * memory for the labels
 + */
-+static int 
-+fdasd_get_partition_data (fdasd_anchor_t *anc,
-+                        extent_t *part_extent,
-+                        partition_info_t *p, unsigned int *start_ptr, unsigned int *stop_ptr) 
++void
++fdasd_initialize_anchor (fdasd_anchor_t * anc) 
 +{
 +PDEBUG
-+      unsigned int limit, cc, hh;
-+      cchh_t llimit, ulimit;
-+      partition_info_t *q;
-+        char mesg[48];
-+      u_int8_t b1, b2;
-+      u_int16_t c, h;
-+      unsigned int start = *start_ptr, stop = *stop_ptr;
-+      int i;
-+      char *ch;
-+
-+      if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
-+              c = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t) anc->f4->DS4DEVAC;
-+      else
-+              c = anc->f4->DS4DEVCT.DS4DSCYL;
++        int i;
++      volume_label_t  *v;
++      partition_info_t *p = NULL;
++      partition_info_t *q = NULL;
 +
-+      h = anc->f4->DS4DEVCT.DS4DSTRK;
-+      limit = (h * c - 1);
++      anc->devno             = 0;
++      anc->dev_type          = 0;
++      anc->used_partitions   = 0;
 +
-+      /* check start value from user */
-+      q = anc->first;
-+      for (i = 0; i < USABLE_PARTITIONS; i++)
-+      {
-+              if ( q->next == NULL )
-+                      break;
-+              if (start >= q->start_trk && start <= q->end_trk)
-+              {
-+                      /* start is within another partition */
-+                      start = q->end_trk + 1;
-+                      if (start > limit)
-+                      {
-+                              start = FIRST_USABLE_TRK;
-+                              q = anc->first;
-+                      }
++      anc->silent            = 0;
++      anc->verbose           = 0;
++      anc->big_disk          = 0;
++      anc->volid_specified   = 0;
++      anc->config_specified  = 0;
++      anc->auto_partition    = 0;
++      anc->devname_specified = 0;
++      anc->print_table       = 0;
 +
-+/*
-+                      printf("value within another partition, " \
-+                             "using %d instead\n", start);
-+*/
-+              }
++      anc->option_reuse      = 0;
++      anc->option_recreate   = 0;
 +
-+              if (start < q->start_trk)
-+              {
-+                      limit = q->start_trk - 1;
-+                      break;
-+              }
-+              q = q->next;
-+      }
++        anc->vlabel_changed    = 0;
++      anc->vtoc_changed      = 0;
++      anc->blksize           = 0;
++      anc->fspace_trk        = 0;
++      anc->label_pos         = 0;
 +
-+      if (start == limit)
-+              stop = start;
++      for (i=0; i<USABLE_PARTITIONS; i++)
++              setpos(anc, i, -1);
 +
-+      /* update partition info */
-+      p->len_trk    = stop - start + 1;
-+      p->start_trk  = start;
-+      p->end_trk    = stop;
++      bzero(anc->confdata, sizeof(config_data_t));
 +
-+      cc = start / anc->geo.heads;
-+      hh = start - (cc * anc->geo.heads);
-+      vtoc_set_cchh(&llimit, cc, hh);
++      anc->f4 = malloc(sizeof(format4_label_t));
++      if (anc->f4 == NULL) 
++              fdasd_error(anc, malloc_failed, 
++                          "FMT4 DSCB memory allocation failed.");
 +
-+      /* check for cylinder boundary */
-+      if (hh == 0)  
-+              b1 = 0x81;
-+      else
-+              b1 = 0x01;
++      anc->f5 = malloc(sizeof(format5_label_t));
++      if (anc->f5 == NULL) 
++              fdasd_error(anc, malloc_failed,
++                          "FMT5 DSCB memory allocation failed.");
 +
-+      cc = stop / anc->geo.heads;
-+      hh = stop - cc * anc->geo.heads;
-+      vtoc_set_cchh(&ulimit, cc, hh);
++      anc->f7 = malloc(sizeof(format7_label_t));
++      if (anc->f7 == NULL) 
++              fdasd_error(anc, malloc_failed,
++                          "FMT7 DSCB memory allocation failed.");
 +
-+        /* it is always the 1st extent */
-+      b2 = 0x00;
++      bzero(anc->f4, sizeof(format4_label_t));
++      bzero(anc->f5, sizeof(format5_label_t));
++      bzero(anc->f7, sizeof(format7_label_t));
 +
-+      vtoc_set_extent(part_extent, b1, b2, &llimit, &ulimit);
++      v = malloc(sizeof(volume_label_t));
++      if (v == NULL) 
++              fdasd_error(anc, malloc_failed,
++                          "Volume label memory allocation failed.");
++      bzero(v, sizeof(volume_label_t));
++      anc->vlabel = v;
 +
-+      *start_ptr = start;
-+      *stop_ptr = stop;
++      for (i=1; i<=USABLE_PARTITIONS; i++) 
++      {
++              p = malloc(sizeof(partition_info_t));
++              if (p == NULL) 
++                      fdasd_error(anc, malloc_failed,
++                                 "Partition info memory allocation failed.");
++              p->used       = 0x00;
++              p->len_trk    = 0;
++              p->start_trk  = 0;
++              p->fspace_trk = 0;
++              p->type       = 0;
 +
-+      ch = p->f1->DS1DSNAM;
-+      vtoc_ebcdic_dec (ch, ch, 44);
-+      if (strstr(ch, PART_TYPE_LVM))
-+              p->type = PARTITION_LINUX_LVM;
-+      else if (strstr(ch, PART_TYPE_RAID))
-+              p->type = PARTITION_LINUX_RAID;
-+      else if (strstr(ch, PART_TYPE_NATIVE))
-+              p->type = PARTITION_LINUX;
-+      else if (strstr(ch, PART_TYPE_SWAP))
-+              p->type = PARTITION_LINUX_SWAP;
-+      else
-+              p->type = PARTITION_LINUX;
-+      vtoc_ebcdic_enc (ch, ch, 44);
++              /* add p to double pointered list */
++              if (i == 1) 
++              {
++                      anc->first = p;
++                      p->prev = NULL;
++              } 
++              else if (i == USABLE_PARTITIONS) 
++              {
++                      anc->last = p;
++                      p->next = NULL;
++                      p->prev = q;
++                      q->next = p;
++              } 
++              else 
++              {
++                      p->prev = q;
++                      q->next = p;
++              }
 +
-+      return 0;
++              p->f1 = malloc(sizeof(format1_label_t));
++              if (p->f1 == NULL) 
++                      fdasd_error(anc, malloc_failed,
++                          "FMT1 DSCB memory allocation failed.");
++              bzero(p->f1, sizeof(format1_label_t));
++              
++              q = p;
++      }
 +}
 +
 +
 +/*
-+ *
++ * call IOCTL to re-read the partition table
 + */
 +static void
-+fdasd_enqueue_new_partition (fdasd_anchor_t *anc) 
++fdasd_reread_partition_table (fdasd_anchor_t * anc, int fd)
 +{
 +PDEBUG
-+        partition_info_t *q = anc->first, *p = anc->last;
-+      int i,k=0;
++      char str[LINE_LENGTH];
++      int f;
 +
-+      for (i=1; i<USABLE_PARTITIONS; i++) 
-+      {
-+              if ((q->end_trk == 0) || 
-+                  (p->start_trk < q->start_trk))
-+                      break;
-+              else
-+              { 
-+                      q = q->next;
-+                      k++;
-+              }
-+      }
++      if (ioctl (fd, BLKRRPART, NULL) != 0)
++              fdasd_error (anc, unable_to_ioctl, "Error while rereading "
++                              "partition table.\nPlease reboot!");
++}
 +
-+      if (anc->first == q) anc->first = p;
-+      
-+      if (p != q) 
-+      {
-+              anc->last->prev->next = NULL;
-+              anc->last = anc->last->prev;
 +
-+              p->next = q;
-+              p->prev = q->prev;
-+              q->prev = p;
-+              
-+              if (p->prev != NULL)
-+                      p->prev->next = p;
-+      }
++/*
++ * writes all changes to dasd
++ */
++static void
++fdasd_write_vtoc_labels (fdasd_anchor_t * anc, int fd)
++{ 
++PDEBUG
++      partition_info_t *p;
++      unsigned long b;
++      char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
++      int i = 0, k = 0;
++    
++      b = (cchhb2blk (&anc->vlabel->vtoc, &anc->geo) - 1) * anc->blksize;
++      if (b <= 0)
++              fdasd_error (anc, vlabel_corrupted, "");
 +
-+      p->used       = 0x01;
-+      p->type       = PARTITION_LINUX;
++      /* write FMT4 DSCB */
++      vtoc_write_label (fd, b, NULL, anc->f4, NULL, NULL);
 +
-+      for (i=0; i<USABLE_PARTITIONS; i++)
++      /* write FMT5 DSCB */
++      b += anc->blksize;
++      vtoc_write_label (fd, b, NULL, NULL, anc->f5, NULL);
++
++      /* write FMT7 DSCB */
++      if (anc->big_disk)
 +      {
-+              int j = getpos(anc, i);
-+              if (j >= k) setpos(anc, i, j + 1);
++              b += anc->blksize;
++              vtoc_write_label (fd, b, NULL, NULL, NULL, anc->f7);
 +      }
 +
-+      /* update free-space counters */
-+      if (anc->first == p) 
++      /* loop over all FMT1 DSCBs */
++      p = anc->first;
++      for (i = 0; i < USABLE_PARTITIONS; i++)
 +      {
-+              /* partition is the first used partition */
-+              if (p->start_trk == FIRST_USABLE_TRK) 
++              b += anc->blksize;
++
++              if (p->used != 0x01)
 +              {
-+                     /* partition starts right behind VTOC */
-+                     p->fspace_trk = anc->fspace_trk - p->len_trk;
-+                     anc->fspace_trk = 0;
++                      vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
++                      continue;
 +              }
-+              else 
-+              {
-+                     /* there is some space between VTOC and partition */
++  
++              strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
 +
-+                     p->fspace_trk   = anc->fspace_trk - 
-+                                       p->len_trk -
-+                                       p->start_trk +
-+                                       FIRST_USABLE_TRK;
-+                     anc->fspace_trk = p->start_trk - FIRST_USABLE_TRK;
-+              }
-+      }
-+      else
-+      {
-+              /* there are partitons in front of the new one */
-+              if (p->start_trk == p->prev->end_trk + 1) 
++              ch = p->f1->DS1DSNAM;
++              vtoc_ebcdic_dec (ch, ch, 44);
++              c1 = ch + 7;
++  
++              if (getdsn (anc, i) > -1)
 +              {
-+                      /* new partition is right behind the previous one */
-+                      p->fspace_trk = p->prev->fspace_trk - p->len_trk;
-+                      p->prev->fspace_trk = 0;
++                      /* re-use the existing data set name */
++                      c2 = strchr (c1, '.');
++                      if (c2 != NULL)
++                              strncpy (s2, c2, 31);
++                      else
++                              fdasd_error (anc, dsname_corrupted, "");
++
++                      strncpy (s1, anc->vlabel->volid, 6);
++                      vtoc_ebcdic_dec (s1, s1, 6);
++                      s1[6] = ' ';
++                      strncpy (c1, s1, 7);
++                      c1 = strchr (ch, ' ');
++                      strncpy (c1, s2, 31);
 +              }
 +              else
 +              {
-+                      /* there is some space between new and prev. part. */
-+                      p->fspace_trk       = p->prev->fspace_trk - 
-+                                            p->len_trk - 
-+                                            p->start_trk +
-+                                            p->prev->end_trk + 1;
-+                      p->prev->fspace_trk = p->start_trk -
-+                                              p->prev->end_trk - 
-+                                            1;
-+              }
-+      }
-+}
++                      /* create a new data set name */
++                      while (getpos (anc, k) > -1)
++                              k++;
 +
++                      setpos (anc, k, i);
 +
-+/*
-+ * adds a new partition to the 'partition table'
-+ */
-+partition_info_t *
-+fdasd_add_partition (fdasd_anchor_t *anc, unsigned int start, unsigned int stop) 
-+{
-+PDEBUG
-+      cchhb_t hf1;
-+      partition_info_t *p;
-+      extent_t ext;
-+      int i;
++                      strncpy (s2, ch, 44);
++                      s2[44] = 0;
++                      vtoc_ebcdic_dec (s2, s2, 44);
 +
-+      PDEBUG;
++                      strncpy (ch, "LINUX.V               " "                      ", 44);
 +
-+      if ((p = fdasd_get_empty_f1_label(anc)) == NULL) 
-+      {
-+      PDEBUG;
-+              return 0;
-+      }
++                      strncpy (s1, anc->vlabel->volid, 6);
++                      vtoc_ebcdic_dec (s1, s1, 6);
++                      strncpy (c1, s1, 6);
 +
-+      PDEBUG;
-+      if (fdasd_get_partition_data(anc, &ext, p, &start, &stop) != 0)
-+              return 0;
++                      c1 = strchr (ch, ' ');
++                      strncpy (c1, ".PART", 5);
++                      c1 += 5;
 +
-+      PDEBUG;
-+      vtoc_init_format1_label(anc->vlabel->volid,
-+                              anc->blksize,
-+                              &ext,
-+                              p->f1);
++                      sprintf (dsno, "%04d.", k + 1);
++                      strncpy (c1, dsno, 5);
 +
++                      c1 += 5;
++                      switch(p->type) {
++                              case PARTITION_LINUX_LVM:
++                                      strncpy(c1, PART_TYPE_LVM, 6);
++                                      break;
++                              case PARTITION_LINUX_RAID:
++                                      strncpy(c1, PART_TYPE_RAID, 6);
++                                      break;
++                              case PARTITION_LINUX:
++                                      strncpy(c1, PART_TYPE_NATIVE, 6);
++                                      break;
++                              case PARTITION_LINUX_SWAP:
++                                      strncpy(c1, PART_TYPE_SWAP, 6);
++                                      break;
++                              default:
++                                      strncpy(c1, PART_TYPE_NATIVE, 6);
++                                      break;
++                      }
++              }
++              vtoc_ebcdic_enc (ch, ch, 44);
 +
-+      PDEBUG;
-+      fdasd_enqueue_new_partition(anc);
-+      
-+      PDEBUG;
-+      anc->used_partitions += 1;
++              vtoc_write_label (fd, b, p->f1, NULL, NULL, NULL);
++              p = p->next;
++      }
++}
 +
-+      i = anc->used_partitions + 2;
-+      if (anc->big_disk) i++;
-+      PDEBUG;
 +
-+        vtoc_set_cchhb(&hf1, VTOC_START_CC, VTOC_START_HH, i);
++/*
++ * writes all changes to dasd
++ */
++int
++fdasd_write_labels (fdasd_anchor_t * anc, int fd)
++{
++PDEBUG
++      if (anc->vlabel_changed)
++      {
++              vtoc_write_volume_label (fd, anc->label_pos, anc->vlabel);
++      }
 +
-+      vtoc_update_format4_label(anc->f4, &hf1, 
-+              anc->f4->DS4DSREC - 1);
++      if (anc->vtoc_changed)
++              fdasd_write_vtoc_labels (anc, fd);
 +
-+      PDEBUG;
++      /*
++      if ((anc->vtoc_changed) || (anc->vlabel_changed))
++              fdasd_reread_partition_table (anc, fd);
 +
-+      start = ext.llimit.cc * anc->geo.heads + ext.llimit.hh;
-+      stop  = ext.ulimit.cc * anc->geo.heads + ext.ulimit.hh;
++      */
 +
-+      PDEBUG;
-+      vtoc_set_freespace(anc->f4, anc->f5, anc->f7, 
-+                         '-', anc->verbose,
-+                         start, stop,
-+                         anc->geo.cylinders, anc->geo.heads);
++      return 1;
++}
 +
-+      anc->vtoc_changed++;
 +
-+      PDEBUG;
-+      return p;
-+}
-diff -ruN --minimal parted-1.6.21.orig/libparted/fdasd.h parted-1.6.21/libparted/fdasd.h
---- parted-1.6.21.orig/libparted/fdasd.h       1969-12-31 19:00:00.000000000 -0500
-+++ parted-1.6.21/libparted/fdasd.h    2005-01-21 15:00:40.429628321 -0500
-@@ -0,0 +1,230 @@
 +/*
-+ * File...........: s390-tools/fdasd/fdasd.h
-+ * Author(s)......: Volker Sameske <sameske@de.ibm.com>
-+ *                  Horst Hummel   <Horst.Hummel@de.ibm.com>
-+ * Bugreports.to..: <Linux390@de.ibm.com>
-+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2001-2002
-+ *
-+ * History of changes (starts March 2001)
-+ * version 1.01 - menu entry 's' to show mapping devnode - DS name
-+ *         1.02 - DS names count now from 0001 instead from 0000
-+ *         1.03 - volser checks: 'AA AAA' to 'AAAAA '
-+ *              - removed dependency to kernel headers.
-+ *         1.04 - added -p option
-+ *         1.05 - new API policy, set it back to 0
++ * writes all changes to dasd
 + */
-+#ifndef FDASD_H
-+#define FDASD_H
-+
-+/*****************************************************************************
-+ * SECTION: Definitions needed for DASD-API (see dasd.h)                     *
-+ *****************************************************************************/
++int
++fdasd_prepare_labels (fdasd_anchor_t *anc, int fd) 
++{
++PDEBUG
++        partition_info_t *p = anc->first;
++      char dsno[6], s1[7], s2[45], *c1, *c2, *ch;
++      int i = 0, k = 0;
 +
-+#define DASD_IOCTL_LETTER 'D'
++      /* loop over all FMT1 DSCBs */
++      p = anc->first;
++      for (i = 0; i < USABLE_PARTITIONS; i++)
++      {
++              strncpy (p->f1->DS1DSSN, anc->vlabel->volid, 6);
 +
-+#define DASD_PARTN_BITS 2
++              ch = p->f1->DS1DSNAM;
++              vtoc_ebcdic_dec (ch, ch, 44);
++              c1 = ch + 7;
++  
++              if (getdsn (anc, i) > -1)
++              {
++                      /* re-use the existing data set name */
++                      c2 = strchr (c1, '.');
++                      if (c2 != NULL)
++                              strncpy (s2, c2, 31);
++                      else
++                              fdasd_error (anc, dsname_corrupted, "");
 +
-+#define PARTITION_LINUX_SWAP    0x82
-+#define PARTITION_LINUX         0x83
-+#define PARTITION_LINUX_EXT     0x85
-+#define PARTITION_LINUX_LVM     0x8e
-+#define PARTITION_LINUX_RAID    0xfd
-+#define PARTITION_LINUX_LVM_OLD 0xfe
++                      strncpy (s1, anc->vlabel->volid, 6);
++                      vtoc_ebcdic_dec (s1, s1, 6);
++                      s1[6] = ' ';
++                      strncpy (c1, s1, 7);
++                      c1 = strchr (ch, ' ');
++                      strncpy (c1, s2, 31);
++              }
++              else
++              {
++                      /* create a new data set name */
++                      while (getpos (anc, k) > -1)
++                              k++;
 +
-+#define PART_TYPE_NATIVE "NATIVE"
-+#define PART_TYPE_SWAP   "SWAP  "
-+#define PART_TYPE_RAID   "RAID  "
-+#define PART_TYPE_LVM   "LVM   "
++                      setpos (anc, k, i);
 +
-+#ifdef DEBUG_DASD
-+#define PDEBUG           fprintf(stderr, "%s:%d:%s\n", \
-+                         __FILE__,                              \
-+                         __LINE__,                              \
-+                         __PRETTY_FUNCTION__);
-+#else
-+#define PDEBUG
-+#endif
++                      strncpy (s2, ch, 44);
++                      s2[44] = 0;
++                      vtoc_ebcdic_dec (s2, s2, 44);
 +
-+/* 
-+ * struct dasd_information_t
-+ * represents any data about the device, which is visible to userspace.
-+ *  including foramt and featueres.
-+ */
-+typedef struct dasd_information_t {
-+        unsigned int devno;           /* S/390 devno                         */
-+        unsigned int real_devno;      /* for aliases                         */
-+        unsigned int schid;           /* S/390 subchannel identifier         */
-+        unsigned int cu_type  : 16;   /* from SenseID                        */
-+        unsigned int cu_model :  8;   /* from SenseID                        */
-+        unsigned int dev_type : 16;   /* from SenseID                        */
-+        unsigned int dev_model : 8;   /* from SenseID                        */
-+        unsigned int open_count; 
-+        unsigned int req_queue_len; 
-+        unsigned int chanq_len;       /* length of chanq                     */
-+        char type[4];                 /* from discipline.name, 'none' for    */
-+                                    /* unknown                             */
-+        unsigned int status;          /* current device level                */
-+        unsigned int label_block;     /* where to find the VOLSER            */
-+        unsigned int FBA_layout;      /* fixed block size (like AIXVOL)      */
-+        unsigned int characteristics_size;
-+        unsigned int confdata_size;
-+        char characteristics[64];     /* from read_device_characteristics    */
-+        char configuration_data[256]; /* from read_configuration_data        */
-+} dasd_information_t;
++                      strncpy (ch, "LINUX.V               " "                      ", 44);
 +
-+/* 
-+ * struct format_data_t
-+ * represents all data necessary to format a dasd
-+ */
-+typedef struct format_data_t {
-+      int start_unit; /* from track */
-+      int stop_unit;  /* to track */
-+      int blksize;    /* sectorsize */
-+        int intensity;  
-+} format_data_t;
++                      strncpy (s1, anc->vlabel->volid, 6);
++                      vtoc_ebcdic_dec (s1, s1, 6);
++                      strncpy (c1, s1, 6);
 +
-+/*
-+ * values to be used for format_data_t.intensity
-+ * 0/8: normal format
-+ * 1/9: also write record zero
-+ * 3/11: also write home address
-+ * 4/12: invalidate track
-+ */
-+#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
-+#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
-+#define DASD_FMT_INT_INVAL  4 /* invalidate tracks */
-+#define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
++                      c1 = strchr (ch, ' ');
++                      strncpy (c1, ".PART", 5);
++                      c1 += 5;
 +
++                      sprintf (dsno, "%04d.", k + 1);
++                      strncpy (c1, dsno, 5);
 +
-+/* Disable the volume (for Linux) */
-+#define BIODASDDISABLE _IO(DASD_IOCTL_LETTER,0) 
-+/* Enable the volume (for Linux) */
-+#define BIODASDENABLE  _IO(DASD_IOCTL_LETTER,1)  
++                      c1 += 5;
++                      switch(p->type) {
++                              case PARTITION_LINUX_LVM:
++                                      strncpy(c1, PART_TYPE_LVM, 6);
++                                      break;
++                              case PARTITION_LINUX_RAID:
++                                      strncpy(c1, PART_TYPE_RAID, 6);
++                                      break;
++                              case PARTITION_LINUX:
++                                      strncpy(c1, PART_TYPE_NATIVE, 6);
++                                      break;
++                              case PARTITION_LINUX_SWAP:
++                                      strncpy(c1, PART_TYPE_SWAP, 6);
++                                      break;
++                              default:
++                                      strncpy(c1, PART_TYPE_NATIVE, 6);
++                                      break;
++                      }
++              }
++              vtoc_ebcdic_enc (ch, ch, 44);
++              p = p->next;
++      }
++      return 1;
++}
 +
-+/* retrieve API version number */
-+#define DASDAPIVER     _IOR(DASD_IOCTL_LETTER,0,int)
-+/* Get information on a dasd device (enhanced) */
-+#define BIODASDINFO   _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
 +
++/*
++ *
++ */
++void
++fdasd_recreate_vtoc(fdasd_anchor_t *anc)
++{
++PDEBUG
++      partition_info_t *p = anc->first;
++      int i;
 +
-+/*****************************************************************************
-+ * SECTION: Further IOCTL Definitions  (see fs.h)                            *
-+ *****************************************************************************/
-+/* re-read partition table */
-+#define BLKRRPART  _IO(0x12,95)       
-+/* get block device sector size */
-+#define BLKSSZGET  _IO(0x12,104)
++      vtoc_init_format4_label(anc->f4,
++                              USABLE_PARTITIONS,
++                              anc->geo.cylinders,
++                              anc->geo.heads,
++                              anc->geo.sectors,
++                              anc->blksize,
++                              anc->dev_type);
 +
-+/*****************************************************************************
-+ * SECTION: Definition from hdreq.h                                          *
-+ *****************************************************************************/
++      vtoc_init_format5_label(anc->f5);
++      vtoc_init_format7_label(anc->f7);
++      vtoc_set_freespace(anc->f4, anc->f5, anc->f7, 
++                         '+', anc->verbose,
++                         FIRST_USABLE_TRK,
++                         anc->geo.cylinders * anc->geo.heads - 1,
++                         anc->geo.cylinders, anc->geo.heads);
 +
-+struct fdasd_hd_geometry {
-+      unsigned char heads;
-+      unsigned char sectors;
-+      unsigned short cylinders;
-+      unsigned long start;
-+};
++      for (i = 0; i < USABLE_PARTITIONS; i++)
++      {
++              bzero(p->f1, sizeof(format1_label_t));
++              p->used       = 0x00;
++              p->start_trk  = 0;
++              p->end_trk    = 0;
++              p->len_trk    = 0;
++              p->fspace_trk = 0;
++              p->type       = 0;
++              p = p->next;
++      }
 +
-+/* get device geometry */
-+#define HDIO_GETGEO           0x0301  
++      anc->used_partitions = 0;
++      anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
 +
-+/*****************************************************************************
-+ * SECTION: FDASD internal types                                             *
-+ *****************************************************************************/
++      for (i=0; i<USABLE_PARTITIONS; i++)
++              setpos(anc, i, -1);
 +
-+#define DASD_MIN_API_VERSION 0
++      anc->vtoc_changed++;
++}
 +
-+#define DEFAULT_FDASD_CONF "/etc/fdasd.conf" /* default config file */
 +
-+#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
-+#define USABLE_PARTITIONS ((1 << DASD_PARTN_BITS) - 1)
++/*
++ * changes the volume serial
++ */
++static void
++fdasd_change_volser (fdasd_anchor_t *anc, char *line_ptr) 
++{
++PDEBUG
++      char str[10];
 +
-+#define FDASD_VERSION "1.05"
-+#define FDASD_ERROR "fdasd error: "
-+#define DEVICE "device"
-+#define DISC   "disc"
-+#define PART   "part"
++        if (strcmp(line_ptr, "") != 0) 
++      {
++              int i;
 +
-+#define ALTERNATE_CYLINDERS_USED 0x10
++              /* fill with blanks if necessary and remove the linebreak */
++              i = strlen(line_ptr);
++              if (i <= 6)
++              {
++                      strncpy(line_ptr + i - 1, "      ", 6);
++              }
 +
-+typedef struct partition_info {
-+        u_int8_t           used;
-+        unsigned long      start_trk;
-+        unsigned long      end_trk;
-+        unsigned long      len_trk;
-+        unsigned long      fspace_trk;
-+        format1_label_t  * f1; 
-+        struct partition_info *next;
-+        struct partition_info *prev;
-+        u_int8_t           type;
-+} partition_info_t;
++              strncpy(str, line_ptr, 6);
 +
++              for (i=0; i<6; i++) str[i] = toupper(str[i]);
++              str[6] = 0x00;
 +
-+typedef struct config_data {
-+      unsigned long start;
-+      unsigned long stop;
-+} config_data_t;
++              fdasd_check_volser (str, anc->devno);
++              vtoc_volume_label_set_volser(anc->vlabel, str);
 +
++              vtoc_set_cchhb(&anc->vlabel->vtoc, 0x0000, 0x0001, 0x01);
++              anc->vlabel_changed++;
++              anc->vtoc_changed++;
++      }
++}
 +
-+typedef struct fdasd_anchor {
-+        int vlabel_changed;
-+        int vtoc_changed;
-+      int devname_specified;
-+      int volid_specified;
-+      int config_specified;
-+      int auto_partition;
-+      int print_table;
-+      int big_disk;
-+      int silent;
-+      int verbose;
-+      int devno;
-+      int option_reuse;
-+      int option_recreate;
-+      int partno[USABLE_PARTITIONS];
-+      u_int16_t dev_type;
-+      unsigned int used_partitions;
-+      unsigned long label_pos;
-+        unsigned int  blksize;
-+        unsigned long fspace_trk;
-+        format4_label_t  *f4;
-+        format5_label_t  *f5;
-+      format7_label_t  *f7;
-+        partition_info_t *first;
-+        partition_info_t *last;
-+        volume_label_t   *vlabel;
-+      config_data_t confdata[USABLE_PARTITIONS];
-+      struct fdasd_hd_geometry geo;
-+} fdasd_anchor_t;
 +
-+enum offset {lower, upper};
++/*
++ * sets some important partition data
++ * (like used, start_trk, end_trk, len_trk)
++ * by calculating these values with the
++ * information provided in the labels
++ */
++static void
++fdasd_update_partition_info (fdasd_anchor_t *anc) 
++{
++PDEBUG
++      partition_info_t *q = NULL, *p = anc->first;
++      unsigned int h = anc->geo.heads;
++      unsigned long max = anc->geo.cylinders * h - 1;
++      int i;
++      char *ch;
 +
-+enum fdasd_failure {
-+      unable_to_open_disk,
-+      unable_to_seek_disk,
-+      unable_to_read_disk,
-+      read_only_disk,
-+        unable_to_ioctl,
-+      api_version_mismatch,
-+      wrong_disk_type,
-+      wrong_disk_format,
-+      disk_in_use,
-+      config_syntax_error,
-+      vlabel_corrupted,
-+      dsname_corrupted,
-+      malloc_failed,
-+      device_verification_failed
-+};
++      anc->used_partitions = anc->geo.sectors - 2 - anc->f4->DS4DSREC;
 +
-+void fdasd_cleanup (fdasd_anchor_t *anchor);
-+void fdasd_initialize_anchor (fdasd_anchor_t * anc);
-+void fdasd_get_geometry (fdasd_anchor_t *anc, int fd);
-+void fdasd_check_api_version (fdasd_anchor_t *anc, int fd);
-+int fdasd_check_volume (fdasd_anchor_t *anc, int fd);
-+int fdasd_write_labels (fdasd_anchor_t *anc, int fd);
-+int fdasd_invalid_vtoc_pointer(fdasd_anchor_t *anc);
-+void fdasd_recreate_vtoc(fdasd_anchor_t *anc);
-+partition_info_t * fdasd_add_partition (fdasd_anchor_t *anc, unsigned int start, unsigned int stop);
-+int fdasd_prepare_labels (fdasd_anchor_t *anc, int fd) ;
++      for (i = 1; i <= USABLE_PARTITIONS; i++)
++      {
++              if (p->f1->DS1FMTID != 0xf1)
++              {
++                      if (i == 1)
++                              /* there is no partition at all */
++                              anc->fspace_trk = max - FIRST_USABLE_TRK + 1;
++                      else
++                              /* previous partition was the last one */
++                              q->fspace_trk = max - q->end_trk;
++                      break;
++              }
 +
-+#endif /* FDASD_H */
---- parted-1.6.23/libparted/libparted.c.orig   2005-03-29 02:01:22.000000000 +0200
-+++ parted-1.6.23/libparted/libparted.c        2005-07-18 20:57:09.847100720 +0200
-@@ -87,12 +87,17 @@
- extern void ped_disk_pc98_init ();
- extern void ped_disk_sun_init ();
- extern void ped_disk_amiga_init ();
-+extern void ped_disk_dasd_init ();
- static void
- init_disk_types ()
- {
-       ped_disk_loop_init ();  /* must be last in the probe list */
-+#if defined(__s390__) || defined(__s390x__)
-+      ped_disk_dasd_init();
-+#endif
++              /* this is a valid format 1 label */
++              p->used = 0x01;
++              p->start_trk = p->f1->DS1EXT1.llimit.cc * h +
++                             p->f1->DS1EXT1.llimit.hh;
++              p->end_trk   = p->f1->DS1EXT1.ulimit.cc * h +
++                             p->f1->DS1EXT1.ulimit.hh;
++              p->len_trk   = p->end_trk - p->start_trk + 1;
 +
-       ped_disk_sun_init ();
- #ifdef ENABLE_PC98
-       ped_disk_pc98_init ();
-@@ -142,10 +147,14 @@
- extern void ped_disk_pc98_done ();
- extern void ped_disk_sun_done ();
- extern void ped_disk_amiga_done ();
-+extern void ped_disk_dasd_done ();
- static void
- done_disk_types ()
- {
-+#if defined(__s390__) || defined(__s390x__)
-+      ped_disk_dasd_done ();
-+#endif
-       ped_disk_sun_done ();
- #ifdef ENABLE_PC98
-       ped_disk_pc98_done ();
-@@ -282,8 +291,9 @@
-               return NULL;
-       }
-+      memset (mem, 0, size);
- #ifdef DEBUG
--      memset (mem, 0xff, size);
-+      /* memset (mem, 0xff, size); */
-       _check_dodgy_pointer (mem, size, 1);
- #endif
-diff -ruN --minimal parted-1.6.21.orig/libparted/linux.c parted-1.6.21/libparted/linux.c
---- parted-1.6.21.orig/libparted/linux.c       2005-01-15 20:01:57.000000000 -0500
-+++ parted-1.6.21/libparted/linux.c    2005-01-21 15:04:40.574398622 -0500
-@@ -60,6 +60,9 @@
- #define HDIO_GETGEO           0x0301  /* get device geometry */
- #define HDIO_GET_IDENTITY     0x030d  /* get IDE identification info */
-+#include "vtoc.h"
-+#include "fdasd.h"
++              if (i == 1)
++                      /* first partition, there is at least one */
++                      anc->fspace_trk = p->start_trk - FIRST_USABLE_TRK;
++              else
++              {
++                      if (i == USABLE_PARTITIONS)
++                              /* last possible partition */
++                              p->fspace_trk = max - p->end_trk;
 +
- struct hd_geometry {
-       unsigned char heads;
-       unsigned char sectors;
-@@ -215,6 +218,8 @@
- #define I2O_MAJOR7            86
- #define I2O_MAJOR8            87
-+#define DASD_MAJOR            94
-+
- #define SCSI_BLK_MAJOR(M) (                                           \
-               (M) == SCSI_DISK0_MAJOR                                 \
-               || (M) == SCSI_CDROM_MAJOR                              \
-@@ -302,6 +307,8 @@
-               dev->type = PED_DEVICE_DAC960;
-       } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
-               dev->type = PED_DEVICE_ATARAID;
-+      } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
-+              dev->type = PED_DEVICE_DASD;
-       } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
-               dev->type = PED_DEVICE_I2O;
-       } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
-@@ -363,6 +370,14 @@
-       if (ioctl (arch_specific->fd, BLKSSZGET, &sector_size))
-               return PED_SECTOR_SIZE;
-+      /*
-+       * We return PED_SECTOR_SIZE, cause, we do not want to fiddle around with b0rken
-+       * parted and kernel for DASDs!!
-+       */
-+      if(dev->type == PED_DEVICE_DASD) {
-+              return PED_SECTOR_SIZE;
-+      }
++                      /* set free space values of previous partition */
++                      q->fspace_trk = p->start_trk - q->end_trk - 1;
++              }
 +
-       if (sector_size != PED_SECTOR_SIZE) {
-               if (ped_exception_throw (
-                       PED_EXCEPTION_BUG,
-@@ -696,6 +711,44 @@
- }
- static int
-+init_dasd (PedDevice* dev, char* model_name)
-+{
-+      struct stat             dev_stat;
-+      PedExceptionOption      ex_status;
-+        int f, blksize = 0;
-+        dasd_information_t dasd_info;
-+        char *errstr = 0;
-+        struct hd_geometry geo;
-+
-+
-+      if (!_device_stat (dev, &dev_stat))
-+              goto error;
-+
-+      if (!ped_device_open (dev))
-+              goto error;
-+
-+      LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
-+
-+      if (!_device_probe_geometry (dev)) 
-+        goto error_close_dev;
-+
-+      dev->model = strdup (model_name);
-+
-+      ped_device_close (dev);
-+      return 1;
-+
-+except:
-+        ped_exception_throw ( PED_EXCEPTION_ERROR,
-+                              PED_EXCEPTION_IGNORE_CANCEL,
-+                              errstr );
++              ch = p->f1->DS1DSNAM;
++              vtoc_ebcdic_dec (ch, ch, 44);
++              if (strstr(ch, PART_TYPE_LVM))
++                      p->type = PARTITION_LINUX_LVM;
++              else if (strstr(ch, PART_TYPE_RAID))
++                      p->type = PARTITION_LINUX_RAID;
++              else if (strstr(ch, PART_TYPE_NATIVE))
++                      p->type = PARTITION_LINUX;
++              else if (strstr(ch, PART_TYPE_SWAP))
++                      p->type = PARTITION_LINUX_SWAP;
++              else
++                      p->type = PARTITION_LINUX;
++              vtoc_ebcdic_enc (ch, ch, 44);
 +
-+error_close_dev:
-+      ped_device_close (dev);
-+error:
-+      return 0;
++              q = p;
++              p = p->next;
++      }
 +}
 +
-+static int
- init_generic (PedDevice* dev, char* model_name)
- {
-       struct stat             dev_stat;
-@@ -719,8 +772,8 @@
-                               PED_EXCEPTION_WARNING,
-                               PED_EXCEPTION_IGNORE_CANCEL,
-                               _("Unable to determine geometry of "
--                              "file/device.  You should not use Parted "
--                              "unless you REALLY know what you're doing!"));
-+                              "file/device %s.  You should not use Parted "
-+                              "unless you REALLY know what you're doing!"), dev->path);
-               switch (ex_status) {
-                       case PED_EXCEPTION_CANCEL:
-                               goto error_close_dev;
-@@ -795,6 +848,11 @@
-                       goto error_free_arch_specific;
-               break;
-+      case PED_DEVICE_DASD:
-+              if (!init_dasd (dev, _("IBM S390 DASD drive")))
-+                      goto error_free_arch_specific;
-+              break;
-+
-       case PED_DEVICE_CPQARRAY:
-               if (!init_generic (dev, _("Compaq Smart Array")))
-                       goto error_free_arch_specific;
-@@ -1710,7 +1768,10 @@
-                * created.  Therefore, if using DevFS, we must get the kernel
-                * to re-read and grok the partition table.
-                */
--              if (_have_blkpg () && !_have_devfs ()) {
-+              /* Work around kernel dasd problem so we really do a
-+                 BLKRRPART */
-+              if (disk->dev->type != PED_DEVICE_DASD &&
-+                  _have_blkpg () && !_have_devfs ()) {
-                       if (_disk_sync_part_table (disk))
-                               return 1;
-               }
-diff -ruN --minimal parted-1.6.21.orig/libparted/vtoc.c parted-1.6.21/libparted/vtoc.c
---- parted-1.6.21.orig/libparted/vtoc.c        1969-12-31 19:00:00.000000000 -0500
-+++ parted-1.6.21/libparted/vtoc.c     2005-01-21 15:00:40.454627663 -0500
-@@ -0,0 +1,1352 @@
-+#include "vtoc.h"
-+
-+#ifdef DEBUG_DASD
-+#define PDEBUG           fprintf(stderr, "%s:%d:%s\n", \
-+                        __FILE__,                              \
-+                        __LINE__,                              \
-+                        __PRETTY_FUNCTION__);
-+#else
-+#define PDEBUG
-+#endif
-+
-+#include <parted/parted.h>
-+
-+#include <libintl.h>
-+#if ENABLE_NLS
-+#  define _(String) dgettext (PACKAGE, String)
-+#else
-+#  define _(String) (String)
-+#endif /* ENABLE_NLS */
-+
-+static unsigned char EBCtoASC[256] =
-+{
-+/* 0x00  NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
-+      0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
-+/* 0x08  -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
-+      0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-+/* 0x10  DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
-+                                -ENP  ->LF             */
-+      0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-+/* 0x18  CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
-+                                                  -IUS */
-+      0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-+/* 0x20  -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
-+                                -INP                   */
-+      0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-+/* 0x28  -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
-+                     -SW                               */ 
-+      0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
-+/* 0x30 ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
-+      0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
-+/* 0x38 -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
-+      0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-+/* 0x40   SP   RSP           Ã¤              ----       */
-+      0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
-+/* 0x48                      .     <     (     +     | */
-+      0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-+/* 0x50    &                                      ---- */
-+      0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-+/* 0x58          ÃŸ     !     $     *     )     ;       */
-+      0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
-+/* 0x60    -     /  ----     Ã„  ----  ----  ----       */
-+      0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
-+/* 0x68             ----     ,     %     _     >     ? */ 
-+      0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-+/* 0x70  ---        ----  ----  ----  ----  ----  ---- */
-+      0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-+/* 0x78    *     `     :     #     @     '     =     " */
-+      0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-+/* 0x80    *     a     b     c     d     e     f     g */
-+      0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-+/* 0x88    h     i              ----  ----  ----       */
-+      0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-+/* 0x90    Â°     j     k     l     m     n     o     p */
-+      0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-+/* 0x98    q     r                    ----        ---- */
-+      0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
-+/* 0xA0          ~     s     t     u     v     w     x */
-+      0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-+/* 0xA8    y     z              ----  ----  ----  ---- */
-+      0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-+/* 0xB0    ^                    ----     Â§  ----       */
-+      0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
-+/* 0xB8       ----     [     ]  ----  ----  ----  ---- */
-+      0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
-+/* 0xC0    {     A     B     C     D     E     F     G */
-+      0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-+/* 0xC8    H     I  ----           Ã¶              ---- */
-+      0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
-+/* 0xD0    }     J     K     L     M     N     O     P */
-+      0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
-+/* 0xD8    Q     R  ----           Ã¼                   */
-+      0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
-+/* 0xE0    \           S     T     U     V     W     X */
-+      0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-+/* 0xE8    Y     Z        ----     Ã–  ----  ----  ---- */
-+      0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
-+/* 0xF0    0     1     2     3     4     5     6     7 */
-+      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+/* 0xF8    8     9  ----  ----     Ãœ  ----  ----  ---- */
-+      0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
-+};
-+
-+static unsigned char ASCtoEBC[256] =
-+{
-+    /*00  NL    SH    SX    EX    ET    NQ    AK    BL */
-+      0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
-+    /*08  BS    HT    LF    VT    FF    CR    SO    SI */
-+      0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-+    /*10  DL    D1    D2    D3    D4    NK    SN    EB */
-+      0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
-+    /*18  CN    EM    SB    EC    FS    GS    RS    US */
-+      0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
-+    /*20  SP     !     "     #     $     %     &     ' */
-+      0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
-+    /*28   (     )     *     +     ,     -    .      / */
-+      0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
-+    /*30   0     1     2     3     4     5     6     7 */
-+      0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-+    /*38   8     9     :     ;     <     =     >     ? */
-+      0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
-+    /*40   @     A     B     C     D     E     F     G */
-+      0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-+    /*48   H     I     J     K     L     M     N     O */
-+      0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
-+    /*50   P     Q     R     S     T     U     V     W */
-+      0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
-+    /*58   X     Y     Z     [     \     ]     ^     _ */
-+      0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
-+    /*60   `     a     b     c     d     e     f     g */
-+      0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-+    /*68   h     i     j     k     l     m     n     o */
-+      0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
-+    /*70   p     q     r     s     t     u     v     w */
-+      0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
-+    /*78   x     y     z     {     |     }     ~    DL */
-+      0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-+      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
-+};
-+
-+enum failure {unable_to_open,
-+            unable_to_seek,
-+            unable_to_write,
-+            unable_to_read};
-+
-+static char buffer[85];
 +
 +/*
-+ *
++ * reorganizes all FMT1s, after that all used FMT1s should be right in 
++ * front of all unused FMT1s
 + */
-+static void 
-+vtoc_error(enum failure why, char *s1, char *s2
++static void
++fdasd_reorganize_FMT1s (fdasd_anchor_t *anc
 +{
-+      PDEBUG
-+        char    error[LINE_LENGTH];
++PDEBUG
++      int i, j;
++      format1_label_t *ltmp;
++      partition_info_t *ptmp;
 +
-+      switch (why) 
++      for (i=1; i<=USABLE_PARTITIONS - 1; i++)
 +      {
-+      case unable_to_open:
-+              sprintf(error, _("%s opening device '%s' failed.\n%s\n"),
-+                      VTOC_ERROR, s1, s2);
-+              break;
-+      case unable_to_seek:
-+              sprintf(error, _("%s seeking device '%s' failed.\n%s\n"),
-+                      VTOC_ERROR, s1, s2);
-+              break;
-+      case unable_to_write:
-+              sprintf(error, _("%s writing to device '%s' failed,\n%s\n"),
-+                      VTOC_ERROR, s1, s2);
-+              break;
-+      case unable_to_read:
-+              sprintf(error, _("%s reading from device '%s' failed.\n%s\n"),
-+                      VTOC_ERROR, s1, s2);
-+              break;
-+      default: sprintf(error, _("Fatal error\n"));
++              ptmp = anc->first;
++              for (j=1; j<=USABLE_PARTITIONS - i; j++)
++              {
++                      if (ptmp->f1->DS1FMTID < ptmp->next->f1->DS1FMTID)
++                      {
++                              ltmp = ptmp->f1;
++                              ptmp->f1 = ptmp->next->f1;
++                              ptmp->next->f1 = ltmp;
++                      }
++                      ptmp=ptmp->next;
++              }
 +      }
-+
-+        ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, error);
 +}
 +
 +
 +/*
 + *
 + */
-+char * 
-+vtoc_ebcdic_enc (char source[LINE_LENGTH],
-+               char target[LINE_LENGTH],
-+               int l) 
++static void
++fdasd_process_valid_vtoc (fdasd_anchor_t * anc, unsigned long b, int fd)
 +{
-+      PDEBUG
-+        int i;
++PDEBUG
++      int f5_counter = 0, f7_counter = 0, f1_counter = 0, oldfmt = 0;
++      int i, n, f1size = sizeof (format1_label_t);
++      partition_info_t *p = anc->first;
++      format1_label_t q;
++      char s[5], *ch;
 +
-+      for (i = 0; i < l; i++) 
-+              target[i]=ASCtoEBC[(unsigned char)(source[i])];
++      b += anc->blksize;
 +
-+      return target;
-+}
++      for (i = 1; i <= anc->geo.sectors; i++)
++      {
++              bzero (&q, f1size);
++              vtoc_read_label (fd, b, &q, NULL, NULL, NULL);
 +
++              switch (q.DS1FMTID)
++              {
++                      case 0xf1:
++                              if (p == NULL)
++                                      break;
++                              memcpy (p->f1, &q, f1size);
 +
-+/*
-+ *
-+ */
-+char * 
-+vtoc_ebcdic_dec (char source[LINE_LENGTH],
-+               char target[LINE_LENGTH],
-+               int l) 
-+{
-+      PDEBUG
-+        int i;
++                              n = -1;
++                              vtoc_ebcdic_dec (p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
++                              ch = strstr (p->f1->DS1DSNAM, "PART");
++                              if (ch != NULL)
++                              {
++                                      strncpy (s, ch + 4, 4);
++                                      s[4] = '\0';
++                                      n = atoi (s) - 1;
++                              }
 +
-+      for (i = 0; i < l; i++) 
-+              target[i]=EBCtoASC[(unsigned char)(source[i])];
++                              vtoc_ebcdic_enc (p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
 +
-+      return target;
-+}
++                              /* this dasd has data set names 0000-0002
++                              but we use now 0001-0003 */
++                              if (n == -1)
++                                      oldfmt++;
 +
++                              if (((oldfmt == 0) && (n < 0)) || (n >= USABLE_PARTITIONS))
++                              {
++                              }
++                              else
++                              {
++                                      if (oldfmt)       /* correct +1 */
++                                      {
++                                              setpos (anc, n + 1, f1_counter);
++                                      }
++                                      else
++                                              setpos (anc, n, f1_counter);
++                              }
 +
-+/*
-+ *
-+ */
-+void 
-+vtoc_set_extent (extent_t *ext,
-+               u_int8_t typeind,
-+               u_int8_t seqno,
-+               cchh_t *lower,
-+               cchh_t *upper) 
-+{ 
-+      PDEBUG
-+        ext->typeind = typeind;
-+        ext->seqno   = seqno;
-+        memcpy(&ext->llimit,lower,sizeof(cchh_t));
-+        memcpy(&ext->ulimit,upper,sizeof(cchh_t));
-+}
++                              p = p->next;
++                              f1_counter++;
++                              break;
++                      case 0xf5:
++                              memcpy (anc->f5, &q, f1size);
++                              f5_counter++;
++                              break;
++                      case 0xf7:
++                              if (f7_counter == 0)
++                                      memcpy (anc->f7, &q, f1size);
++                              f7_counter++;
++                              break;
++              }
++              b += anc->blksize;
++      }
 +
++      if (oldfmt > 0)
++      {
++              /* this is the old format PART0000 - PART0002 */
++              anc->vtoc_changed++;
++      }
 +
-+/*
-+ *
-+ */
-+void 
-+vtoc_set_cchh (cchh_t *addr,
-+               u_int16_t cc,
-+               u_int16_t hh) 
-+{
-+      PDEBUG
-+        addr->cc = cc;
-+      addr->hh = hh;
-+}
++      if ((f5_counter == 0) || (anc->big_disk))
++              vtoc_init_format5_label (anc->f5);
 +
++      if (f7_counter == 0)
++              vtoc_init_format7_label (anc->f7);
 +
-+/*
-+ *
-+ */
-+static void 
-+vtoc_set_ttr (ttr_t *addr,
-+              u_int16_t tt,
-+              u_int8_t r) 
-+{
-+      PDEBUG
-+        addr->tt = tt;
-+      addr->r = r;
++      fdasd_reorganize_FMT1s (anc);
++      fdasd_update_partition_info (anc);
 +}
 +
 +
 +/*
 + *
 + */
-+void 
-+vtoc_set_cchhb (cchhb_t *addr,
-+              u_int16_t cc,
-+              u_int16_t hh,
-+              u_int8_t b) 
++static int
++fdasd_valid_vtoc_pointer(fdasd_anchor_t *anc, unsigned long b, int fd)
 +{
-+      PDEBUG
-+        addr->cc = cc;
-+        addr->hh = hh;
-+        addr->b = b;
-+}
-+
++PDEBUG
++      char str[LINE_LENGTH];
 +
-+/*
-+ *
-+ */
-+void 
-+vtoc_set_date (
-+        labeldate_t * d,
-+      u_int8_t year,
-+      u_int16_t day) 
-+{
-+      PDEBUG
-+        d->year = year;
-+        d->day = day;
-+}
++      /* VOL1 label contains valid VTOC pointer */ 
++      vtoc_read_label (fd, b, NULL, anc->f4, NULL, NULL);
 +
++      if (anc->f4->DS4IDFMT != 0xf4)
++      {
++              if (strncmp (anc->vlabel->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
++                      return 0;
++              /* format4 DSCB is invalid
++              printf(" invalid\ncreating new VTOC...\n"); */
++              fdasd_error(anc, wrong_disk_format, "Invalid VTOC");
++      }
++      else
++              fdasd_process_valid_vtoc (anc, b, fd);
 +
-+/*
-+ * initializes the volume label with EBCDIC spaces
-+ */
-+void
-+vtoc_volume_label_init (volume_label_t *vlabel)
-+{
-+      PDEBUG
-+      sprintf(buffer, "%84s", " ");
-+      vtoc_ebcdic_enc(buffer, buffer, 84);    
-+      strncpy(vlabel->volkey, buffer, 84);
++      return 0;
 +}
 +
 +
 +/*
-+ * reads the volume label from dasd
++ * check the dasd for a volume label
 + */
 +int 
-+vtoc_read_volume_label (
-+        int f,
-+        unsigned long vlabel_start,
-+        volume_label_t *vlabel) 
++fdasd_check_volume (fdasd_anchor_t *anc, int fd) 
 +{
-+      PDEBUG
-+      int rc;
++PDEBUG
++      volume_label_t *v = anc->vlabel;
++      unsigned long b = -1;
++      char str[LINE_LENGTH];
 +
-+      if (lseek(f, vlabel_start, SEEK_SET) == -1) 
++      vtoc_read_volume_label (fd, anc->label_pos, v);
++
++      if (strncmp (v->vollbl, vtoc_ebcdic_enc ("VOL1", str, 4), 4) == 0)
 +      {
-+              vtoc_error(unable_to_seek, "vtoc_read_volume_label",
-+                         "Could not read volume label.");
-+              return 1;
-+      }
++              /* found VOL1 volume label */
++              b = (cchhb2blk (&v->vtoc, &anc->geo) - 1) * anc->blksize;
++              if (b > 0)
++              {
++                      int rc;
++                      rc = fdasd_valid_vtoc_pointer (anc, b, fd);
 +
-+      rc = read(f, vlabel, sizeof(volume_label_t));
-+      if (rc != sizeof(volume_label_t)) 
++                      if (rc < 0)
++                              return 1;
++                      else
++                              return 0;
++              }
++              else 
++              {
++                      return 1;
++              }
++        }
++      else if (strncmp (v->volkey, vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0)
 +      {
-+              vtoc_error(unable_to_read, "vtoc_read_volume_label",
-+                         "Could not read volume label.");
-+              return 1;
++              return 0;
 +      }
 +
-+      return 0;
++        return 1;
 +}
 +
 +
 +/*
-+ * writes the volume label to dasd
++ * checks the current API version with the API version of the dasd driver
 + */
-+int 
-+vtoc_write_volume_label (
-+        int f,
-+      unsigned long vlabel_start,
-+      volume_label_t *vlabel) 
++void
++fdasd_check_api_version (fdasd_anchor_t *anc, int f)
 +{
-+      PDEBUG
-+        int rc;
-+
-+      if (lseek(f, vlabel_start, SEEK_SET) == -1) 
-+      {
-+              vtoc_error(unable_to_seek, "vtoc_write_volume_label",
-+                         "Could not write volume label.");
-+      }
-+
-+      rc = write(f, vlabel, sizeof(volume_label_t)); 
-+      if (rc != sizeof(volume_label_t)) 
++PDEBUG
++        int api;
++      char s[LINE_LENGTH];
++ 
++        if (ioctl(f, DASDAPIVER, &api) != 0)
++        {
++                fdasd_error(anc, unable_to_ioctl,
++                            "Could not retrieve API version.");
++        }
++ 
++      if (api != DASD_MIN_API_VERSION)
 +      {
-+              vtoc_error(unable_to_write, "vtoc_write_volume_label",
-+                         "Could not write volume label.");
++              sprintf(s, "The current API version '%d' doesn't " \
++                      "match dasd driver API version " \
++                      "'%d'!", api, DASD_MIN_API_VERSION);
++              fdasd_error(anc, api_version_mismatch, s);
 +      }
-+      return 0;
-+}
++}                                      
 +
 +
 +/*
-+ * takes a string as input, converts it to uppercase, translates
-+ * it to EBCDIC and fills it up with spaces before it copies it
-+ * as volume serial to the volume label
++ * reads dasd geometry data
 + */
-+void
-+vtoc_volume_label_set_volser (
-+      volume_label_t *vlabel, 
-+      char *volser)
++void 
++fdasd_get_geometry (fdasd_anchor_t *anc, int f) 
 +{
-+      PDEBUG
-+      int j, i = strlen(volser);
-+      char s[VOLSER_LENGTH + 1];
-+
-+      strcpy(s, "      ");
-+      vtoc_ebcdic_enc(s, s, VOLSER_LENGTH);
-+      strncpy(vlabel->volid, s, VOLSER_LENGTH);
++PDEBUG
++        int blksize = 0;
++      dasd_information_t dasd_info;
++      char s[LINE_LENGTH];
 +
-+      if (i > VOLSER_LENGTH) i = VOLSER_LENGTH;
++      if (ioctl(f, HDIO_GETGEO, &anc->geo) != 0) 
++      {
++              fdasd_error(anc, unable_to_ioctl, 
++                          "Could not retrieve disk geometry information.");
++      }
 +
-+      strncpy(s, volser, i);
-+      for (j=0; j<i; j++) {
-+              s[j] = toupper(s[j]);
++      if (ioctl(f, BLKSSZGET, &blksize) != 0)
++      {
++              fdasd_error(anc, unable_to_ioctl,
++                          "Could not retrieve blocksize information.");
 +      }
 +
-+      s[VOLSER_LENGTH] = 0x00;
-+      vtoc_ebcdic_enc(s, s, i);
-+      strncpy(vlabel->volid, s, i);
++      /* get disk type */
++      if (ioctl(f, BIODASDINFO, &dasd_info) != 0) 
++      {
++              fdasd_error(anc, unable_to_ioctl, 
++                          "Could not retrieve disk information.");
++      }
 +
-+      return;
-+}
++      if (strncmp(dasd_info.type, "ECKD", 4) != 0)
++      {
++              sprintf(s, "This is not an ECKD disk! This disk type " \
++                      "is not supported!");
++              fdasd_error(anc,wrong_disk_type, s);
++      }
 +
++      /* Disable FBA_layout check
++        if (dasd_info.FBA_layout)
++        {
++         if(!anc->silent) {
++                sprintf(s, "Device is not formatted with z/OS compatible " \
++                      "disk layout!");
++                fdasd_error(anc,wrong_disk_format, s);
++         }
++        }      
++      */
 +
-+/*
-+ * returns the volume serial number right after it is translated 
-+ * to ASCII
-+ */
-+char *
-+vtoc_volume_label_get_volser (
-+      volume_label_t *vlabel,
-+      char *volser)
-+{
-+      PDEBUG
-+      vtoc_ebcdic_dec(vlabel->volid, volser, VOLSER_LENGTH);
++      /* We do not write yet, so let this check go 
++      if (dasd_info.open_count > 1)
++      {
++              sprintf(s, "Device is in use by another program. Exit all " \
++                      "applications using this disk and/or unmount it.");
++              fdasd_error(anc,disk_in_use, s);
++      }
++      */
 +
-+      return volser;
++      anc->dev_type   = dasd_info.dev_type;
++      anc->blksize    = blksize;
++      anc->label_pos  = dasd_info.label_block * blksize;
++      anc->devno      = dasd_info.devno;
++      anc->fspace_trk = anc->geo.cylinders * anc->geo.heads - FIRST_USABLE_TRK;
 +}
 +
-+
-+/*
-+ * sets the volume label key right after
-+ * it has been translated to EBCDIC
-+ */
-+void
-+vtoc_volume_label_set_key (
-+        volume_label_t *vlabel,
-+        char *key)
-+{
-+      PDEBUG
-+        char s[4];
-+ 
-+        vtoc_ebcdic_enc(key, s, 4);
-+        strncpy(vlabel->volkey, s, 4);
-+ 
-+        return;
-+}                
-+
-+
 +/*
-+ * sets the volume label identifier right
-+ * after it has been translated to EBCDIC
++ * returns unused partition info pointer if there
++ * is a free partition, otherwise NULL
 + */
-+void
-+vtoc_volume_label_set_label (
-+      volume_label_t *vlabel,
-+      char *lbl)
++static partition_info_t * 
++fdasd_get_empty_f1_label (fdasd_anchor_t * anc) 
 +{
-+      PDEBUG
-+      char s[4];
-+
-+      vtoc_ebcdic_enc(lbl, s, 4);
-+      strncpy(vlabel->vollbl, s, 4);
-+
-+      return;
++PDEBUG
++      if (anc->used_partitions < USABLE_PARTITIONS)     
++              return anc->last;             
++      else
++              return NULL;
 +}
 +
-+
 +/*
-+ * returns the volume label key = the label identifier
-+ * right after it has been translated to ASCII
++ * asks for and sets some important partition data
 + */
-+char *
-+vtoc_volume_label_get_label (
-+      volume_label_t *vlabel,
-+      char *lbl)
++static int 
++fdasd_get_partition_data (fdasd_anchor_t *anc,
++                        extent_t *part_extent,
++                        partition_info_t *p, unsigned int *start_ptr, unsigned int *stop_ptr) 
 +{
-+      PDEBUG
-+      vtoc_ebcdic_dec(vlabel->vollbl, lbl, 4);
-+
-+      return lbl;
-+}
-+
++PDEBUG
++      unsigned int limit, cc, hh;
++      cchh_t llimit, ulimit;
++      partition_info_t *q;
++        char mesg[48];
++      u_int8_t b1, b2;
++      u_int16_t c, h;
++      unsigned int start = *start_ptr, stop = *stop_ptr;
++      int i;
++      char *ch;
 +
-+/*
-+ * reads either a format4 label or a format1 label
-+ * from the specified position
-+ */
-+void 
-+vtoc_read_label (int f,
-+               unsigned long position,
-+               format1_label_t *f1,
-+               format4_label_t *f4,
-+               format5_label_t *f5,
-+               format7_label_t *f7) 
-+{        
-+      PDEBUG
-+      int t;
++      if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
++              c = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t) anc->f4->DS4DEVAC;
++      else
++              c = anc->f4->DS4DEVCT.DS4DSCYL;
 +
-+        if (lseek(f, position, SEEK_SET) == -1) 
-+      {
-+              vtoc_error(unable_to_seek, "vtoc_read_label",
-+                         _("Could not read VTOC labels."));
-+        }
++      h = anc->f4->DS4DEVCT.DS4DSTRK;
++      limit = (h * c - 1);
 +
-+      if (f1 != NULL)
++      /* check start value from user */
++      q = anc->first;
++      for (i = 0; i < USABLE_PARTITIONS; i++)
 +      {
-+              t = sizeof(format1_label_t);
-+              if (read(f, f1, t) != t) 
++              if ( q->next == NULL )
++                      break;
++              if (start >= q->start_trk && start <= q->end_trk)
 +              {
-+                      vtoc_error(unable_to_read, "vtoc_read_label",
-+                                 _("Could not read VTOC FMT1 DSCB."));
-+              }
-+      }
++                      /* start is within another partition */
++                      start = q->end_trk + 1;
++                      if (start > limit)
++                      {
++                              start = FIRST_USABLE_TRK;
++                              q = anc->first;
++                      }
 +
-+      if (f4 != NULL)
-+      {
-+              t = sizeof(format4_label_t);
-+              if (read(f, f4, t) != t) 
-+              {
-+                      vtoc_error(unable_to_read, "vtoc_read_label",
-+                                 _("Could not read VTOC FMT4 DSCB."));
++/*
++                      printf("value within another partition, " \
++                             "using %d instead\n", start);
++*/
 +              }
-+      }
-+
-+        if (f5 != NULL)
-+      {
-+              t = sizeof(format5_label_t);
-+                if (read(f, f5, t) != t)
-+                {
-+                        vtoc_error(unable_to_read, "vtoc_read_label",
-+                                   _("Could not read VTOC FMT5 DSCB."));
-+                }
-+      }
 +
-+      if (f7 != NULL)
-+      {
-+              t = sizeof(format7_label_t);
-+              if (read(f, f7, t) != t) 
++              if (start < q->start_trk)
 +              {
-+                      vtoc_error(unable_to_read, "vtoc_read_label",
-+                                 _("Could not read VTOC FMT7 DSCB."));
++                      limit = q->start_trk - 1;
++                      break;
 +              }
++              q = q->next;
 +      }
-+}
 +
++      if (start == limit)
++              stop = start;
 +
-+/*
-+ * writes either a FMT1, FMT4 or FMT5 label
-+ * to the specified position
-+ */
-+void
-+vtoc_write_label (int f,
-+                unsigned long position,
-+                format1_label_t *f1, 
-+                format4_label_t *f4,
-+                format5_label_t *f5,
-+                format7_label_t *f7)
-+{
-+      PDEBUG
-+      int t;
++      /* update partition info */
++      p->len_trk    = stop - start + 1;
++      p->start_trk  = start;
++      p->end_trk    = stop;
 +
-+        if (lseek(f, position, SEEK_SET) == -1) 
-+      {
-+              vtoc_error(unable_to_seek, "vtoc_write_label",
-+                         _("Could not write VTOC labels."));
-+        }
++      cc = start / anc->geo.heads;
++      hh = start - (cc * anc->geo.heads);
++      vtoc_set_cchh(&llimit, cc, hh);
 +
-+      if (f1 != NULL)
++      /* check for cylinder boundary */
++      if (hh == 0)  
++              b1 = 0x81;
++      else
++              b1 = 0x01;
++
++      cc = stop / anc->geo.heads;
++      hh = stop - cc * anc->geo.heads;
++      vtoc_set_cchh(&ulimit, cc, hh);
++
++        /* it is always the 1st extent */
++      b2 = 0x00;
++
++      vtoc_set_extent(part_extent, b1, b2, &llimit, &ulimit);
++
++      *start_ptr = start;
++      *stop_ptr = stop;
++
++      ch = p->f1->DS1DSNAM;
++      vtoc_ebcdic_dec (ch, ch, 44);
++      if (strstr(ch, PART_TYPE_LVM))
++              p->type = PARTITION_LINUX_LVM;
++      else if (strstr(ch, PART_TYPE_RAID))
++              p->type = PARTITION_LINUX_RAID;
++      else if (strstr(ch, PART_TYPE_NATIVE))
++              p->type = PARTITION_LINUX;
++      else if (strstr(ch, PART_TYPE_SWAP))
++              p->type = PARTITION_LINUX_SWAP;
++      else
++              p->type = PARTITION_LINUX;
++      vtoc_ebcdic_enc (ch, ch, 44);
++
++      return 0;
++}
++
++
++/*
++ *
++ */
++static void
++fdasd_enqueue_new_partition (fdasd_anchor_t *anc) 
++{
++PDEBUG
++        partition_info_t *q = anc->first, *p = anc->last;
++      int i,k=0;
++
++      for (i=1; i<USABLE_PARTITIONS; i++) 
 +      {
-+              t = sizeof(format1_label_t);
-+              if (write(f, f1, t) != t) 
-+              {
-+                      vtoc_error(unable_to_write, "vtoc_write_label",
-+                                 _("Could not write VTOC FMT1 DSCB."));
++              if ((q->end_trk == 0) || 
++                  (p->start_trk < q->start_trk))
++                      break;
++              else
++              { 
++                      q = q->next;
++                      k++;
 +              }
 +      }
 +
-+      if (f4 != NULL)
++      if (anc->first == q) anc->first = p;
++      
++      if (p != q) 
 +      {
-+              t = sizeof(format4_label_t);
-+              if (write(f, f4, t) != t) 
-+              {
-+                      vtoc_error(unable_to_write, "vtoc_write_label",
-+                                 _("Could not write VTOC FMT4 DSCB."));
-+              }
++              anc->last->prev->next = NULL;
++              anc->last = anc->last->prev;
++
++              p->next = q;
++              p->prev = q->prev;
++              q->prev = p;
++              
++              if (p->prev != NULL)
++                      p->prev->next = p;
 +      }
 +
-+      if (f5 != NULL)
++      p->used       = 0x01;
++      p->type       = PARTITION_LINUX;
++
++      for (i=0; i<USABLE_PARTITIONS; i++)
 +      {
-+              t = sizeof(format5_label_t);
-+              if (write(f, f5, t) != t) 
++              int j = getpos(anc, i);
++              if (j >= k) setpos(anc, i, j + 1);
++      }
++
++      /* update free-space counters */
++      if (anc->first == p) 
++      {
++              /* partition is the first used partition */
++              if (p->start_trk == FIRST_USABLE_TRK) 
 +              {
-+                      vtoc_error(unable_to_write, "vtoc_write_label",
-+                                 _("Could not write VTOC FMT5 DSCB."));
++                     /* partition starts right behind VTOC */
++                     p->fspace_trk = anc->fspace_trk - p->len_trk;
++                     anc->fspace_trk = 0;
 +              }
-+      }
++              else 
++              {
++                     /* there is some space between VTOC and partition */
 +
-+      if (f7 != NULL)
++                     p->fspace_trk   = anc->fspace_trk - 
++                                       p->len_trk -
++                                       p->start_trk +
++                                       FIRST_USABLE_TRK;
++                     anc->fspace_trk = p->start_trk - FIRST_USABLE_TRK;
++              }
++      }
++      else
 +      {
-+              t = sizeof(format7_label_t);
-+              if (write(f, f7, t) != t
++              /* there are partitons in front of the new one */
++              if (p->start_trk == p->prev->end_trk + 1
 +              {
-+                      vtoc_error(unable_to_write, "vtoc_write_label",
-+                                 _("Could not write VTOC FMT7 DSCB."));
++                      /* new partition is right behind the previous one */
++                      p->fspace_trk = p->prev->fspace_trk - p->len_trk;
++                      p->prev->fspace_trk = 0;
++              }
++              else
++              {
++                      /* there is some space between new and prev. part. */
++                      p->fspace_trk       = p->prev->fspace_trk - 
++                                            p->len_trk - 
++                                            p->start_trk +
++                                            p->prev->end_trk + 1;
++                      p->prev->fspace_trk = p->start_trk -
++                                              p->prev->end_trk - 
++                                            1;
 +              }
 +      }
-+
 +}
 +
 +
 +/*
-+ * initializes a format4 label
++ * adds a new partition to the 'partition table'
 + */
-+void 
-+vtoc_init_format4_label (
-+      format4_label_t    *f4,
-+      unsigned int usable_partitions,
-+      unsigned int cylinders,
-+      unsigned int tracks,
-+      unsigned int blocks,
-+      unsigned int blksize,
-+      u_int16_t dev_type) 
++partition_info_t *
++fdasd_add_partition (fdasd_anchor_t *anc, unsigned int start, unsigned int stop) 
 +{
-+      PDEBUG
++PDEBUG
++      cchhb_t hf1;
++      partition_info_t *p;
++      extent_t ext;
 +      int i;
 +
-+      cchh_t lower = {VTOC_START_CC, VTOC_START_HH};
-+      cchh_t upper = {VTOC_START_CC, VTOC_START_HH};
++      PDEBUG;
 +
-+      for (i=0; i<44; i++) f4->DS4KEYCD[i] = 0x04;
-+        f4->DS4IDFMT = 0xf4;
-+      vtoc_set_cchhb(&f4->DS4HPCHR, 0x0000, 0x0000, 0x00);
-+        f4->DS4DSREC = blocks - 2;
-+      /* free space starts right behind VTOC
-+         vtoc_set_cchh(&f4->DS4HCCHH, VTOC_START_CC, VTOC_START_HH + 1);*/
-+        vtoc_set_cchh(&f4->DS4HCCHH, 0x0000, 0x0000);
-+        f4->DS4NOATK = 0x0000;
-+        f4->DS4VTOCI = 0x00;
-+        f4->DS4NOEXT = 0x01;
-+        f4->DS4SMSFG = 0x00;
-+        f4->DS4DEVAC = 0x00;
++      if ((p = fdasd_get_empty_f1_label(anc)) == NULL) 
++      {
++      PDEBUG;
++              return 0;
++      }
 +
-+        /* -- begin f4->DS4DEVCT -- */
-+        f4->DS4DEVCT.DS4DSCYL = cylinders;
-+        f4->DS4DEVCT.DS4DSTRK = tracks;
++      PDEBUG;
++      if (fdasd_get_partition_data(anc, &ext, p, &start, &stop) != 0)
++              return 0;
 +
-+      switch (dev_type)
-+      {
-+      case DASD_3380_TYPE:
-+              f4->DS4DEVCT.DS4DEVTK = DASD_3380_VALUE;
-+              break;
-+      case DASD_3390_TYPE:
-+              f4->DS4DEVCT.DS4DEVTK = DASD_3390_VALUE;
-+              break;
-+      case DASD_9345_TYPE:
-+              f4->DS4DEVCT.DS4DEVTK = DASD_9345_VALUE;
-+              break;
-+        default:
-+              f4->DS4DEVCT.DS4DEVTK = blocks * blksize;;
-+        }
++      PDEBUG;
++      vtoc_init_format1_label(anc->vlabel->volid,
++                              anc->blksize,
++                              &ext,
++                              p->f1);
 +
 +
-+        f4->DS4DEVCT.DS4DEVI  = 0x00;
-+        f4->DS4DEVCT.DS4DEVL  = 0x00;
-+        f4->DS4DEVCT.DS4DEVK  = 0x00;
-+        f4->DS4DEVCT.DS4DEVFG = 0x30;
-+        f4->DS4DEVCT.DS4DEVTL = 0x0000;
-+        f4->DS4DEVCT.DS4DEVDT = blocks;
-+        f4->DS4DEVCT.DS4DEVDB = 0x00;
-+        /* -- end f4->DS4DEVCT -- */
++      PDEBUG;
++      fdasd_enqueue_new_partition(anc);
++      
++      PDEBUG;
++      anc->used_partitions += 1;
 +
-+      bzero(f4->DS4AMTIM, sizeof(f4->DS4AMTIM));
-+      bzero(f4->DS4AMCAT, sizeof(f4->DS4AMCAT));
-+      bzero(f4->DS4R2TIM, sizeof(f4->DS4R2TIM));
-+      bzero(f4->res1, sizeof(f4->res1));
-+      bzero(f4->DS4F6PTR, sizeof(f4->DS4F6PTR));
++      i = anc->used_partitions + 2;
++      if (anc->big_disk) i++;
++      PDEBUG;
 +
-+        /* -- begin f4lbl->DS4VTOCE -- */
-+      vtoc_set_extent(&f4->DS4VTOCE, 0x01, 0x00, &lower, &upper);
-+        /* -- end f4lbl->DS4VTOCE -- */
++        vtoc_set_cchhb(&hf1, VTOC_START_CC, VTOC_START_HH, i);
 +
-+      bzero(f4->res2, sizeof(f4->res2));
-+      f4->DS4EFLVL = 0x00;
-+      bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
-+      bzero(f4->res3, sizeof(f4->res3));
-+}
++      vtoc_update_format4_label(anc->f4, &hf1, 
++              anc->f4->DS4DSREC - 1);
 +
++      PDEBUG;
 +
-+/*
-+ * initializes a format5 label
-+ */
-+void
-+vtoc_init_format5_label (format5_label_t *f5) 
-+{
-+      PDEBUG
-+      int i;
++      start = ext.llimit.cc * anc->geo.heads + ext.llimit.hh;
++      stop  = ext.ulimit.cc * anc->geo.heads + ext.ulimit.hh;
 +
-+      bzero(f5, sizeof(format5_label_t));
-+      for (i=0; i<4; i++) f5->DS5KEYID[i] = 0x05;
-+      f5->DS5FMTID = 0xf5;
-+}
++      PDEBUG;
++      vtoc_set_freespace(anc->f4, anc->f5, anc->f7, 
++                         '-', anc->verbose,
++                         start, stop,
++                         anc->geo.cylinders, anc->geo.heads);
 +
++      anc->vtoc_changed++;
 +
-+/*
-+ * initializes a format7 label
-+ */
-+void
-+vtoc_init_format7_label (format7_label_t *f7) 
++      PDEBUG;
++      return p;
++}
+diff -urN parted-1.7.0.orig/libparted/labels/vtoc.c parted-1.7.0/libparted/labels/vtoc.c
+--- parted-1.7.0.orig/libparted/labels/vtoc.c  1969-12-31 19:00:00.000000000 -0500
++++ parted-1.7.0/libparted/labels/vtoc.c       2006-05-19 14:41:09.000000000 -0400
+@@ -0,0 +1,1343 @@
++#include <parted/vtoc.h>
++
++#ifdef DEBUG_DASD
++#define PDEBUG           fprintf(stderr, "%s:%d:%s\n", \
++                        __FILE__,                              \
++                        __LINE__,                              \
++                        __PRETTY_FUNCTION__);
++#else
++#define PDEBUG
++#endif
++
++#include <parted/parted.h>
++
++#include <libintl.h>
++#if ENABLE_NLS
++#  define _(String) dgettext (PACKAGE, String)
++#else
++#  define _(String) (String)
++#endif /* ENABLE_NLS */
++
++static unsigned char EBCtoASC[256] =
 +{
-+      PDEBUG
-+      int i;
++/* 0x00  NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
++      0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
++/* 0x08  -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
++      0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
++/* 0x10  DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
++                                -ENP  ->LF             */
++      0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
++/* 0x18  CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
++                                                  -IUS */
++      0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++/* 0x20  -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
++                                -INP                   */
++      0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
++/* 0x28  -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
++                     -SW                               */ 
++      0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
++/* 0x30 ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
++      0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
++/* 0x38 -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
++      0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
++/* 0x40   SP   RSP           Ã¤              ----       */
++      0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
++/* 0x48                      .     <     (     +     | */
++      0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
++/* 0x50    &                                      ---- */
++      0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
++/* 0x58          ÃŸ     !     $     *     )     ;       */
++      0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
++/* 0x60    -     /  ----     Ã„  ----  ----  ----       */
++      0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
++/* 0x68             ----     ,     %     _     >     ? */ 
++      0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
++/* 0x70  ---        ----  ----  ----  ----  ----  ---- */
++      0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
++/* 0x78    *     `     :     #     @     '     =     " */
++      0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
++/* 0x80    *     a     b     c     d     e     f     g */
++      0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
++/* 0x88    h     i              ----  ----  ----       */
++      0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
++/* 0x90    Â°     j     k     l     m     n     o     p */
++      0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
++/* 0x98    q     r                    ----        ---- */
++      0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
++/* 0xA0          ~     s     t     u     v     w     x */
++      0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
++/* 0xA8    y     z              ----  ----  ----  ---- */
++      0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
++/* 0xB0    ^                    ----     Â§  ----       */
++      0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
++/* 0xB8       ----     [     ]  ----  ----  ----  ---- */
++      0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
++/* 0xC0    {     A     B     C     D     E     F     G */
++      0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++/* 0xC8    H     I  ----           Ã¶              ---- */
++      0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
++/* 0xD0    }     J     K     L     M     N     O     P */
++      0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
++/* 0xD8    Q     R  ----           Ã¼                   */
++      0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
++/* 0xE0    \           S     T     U     V     W     X */
++      0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
++/* 0xE8    Y     Z        ----     Ã–  ----  ----  ---- */
++      0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
++/* 0xF0    0     1     2     3     4     5     6     7 */
++      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++/* 0xF8    8     9  ----  ----     Ãœ  ----  ----  ---- */
++      0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
++};
 +
-+      bzero(f7, sizeof(format7_label_t));
-+      for (i=0; i<4; i++) f7->DS7KEYID[i] = 0x07;
-+      f7->DS7FMTID = 0xf7;
-+}
++static unsigned char ASCtoEBC[256] =
++{
++    /*00  NL    SH    SX    EX    ET    NQ    AK    BL */
++      0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
++    /*08  BS    HT    LF    VT    FF    CR    SO    SI */
++      0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
++    /*10  DL    D1    D2    D3    D4    NK    SN    EB */
++      0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
++    /*18  CN    EM    SB    EC    FS    GS    RS    US */
++      0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
++    /*20  SP     !     "     #     $     %     &     ' */
++      0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
++    /*28   (     )     *     +     ,     -    .      / */
++      0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
++    /*30   0     1     2     3     4     5     6     7 */
++      0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
++    /*38   8     9     :     ;     <     =     >     ? */
++      0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
++    /*40   @     A     B     C     D     E     F     G */
++      0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
++    /*48   H     I     J     K     L     M     N     O */
++      0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
++    /*50   P     Q     R     S     T     U     V     W */
++      0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
++    /*58   X     Y     Z     [     \     ]     ^     _ */
++      0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
++    /*60   `     a     b     c     d     e     f     g */
++      0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
++    /*68   h     i     j     k     l     m     n     o */
++      0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
++    /*70   p     q     r     s     t     u     v     w */
++      0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
++    /*78   x     y     z     {     |     }     ~    DL */
++      0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++      0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
++};
 +
++enum failure {unable_to_open,
++            unable_to_seek,
++            unable_to_write,
++            unable_to_read};
++
++static char buffer[85];
 +
 +/*
-+ * initializes a format1 label
++ *
 + */
-+void 
-+vtoc_init_format1_label (
-+      char *volid,
-+        unsigned int blksize,
-+      extent_t *part_extent,
-+      format1_label_t *f1) 
++static void 
++vtoc_error(enum failure why, char *s1, char *s2) 
 +{
 +      PDEBUG
-+        struct tm * creatime;
-+      time_t t;
-+      char str[80];
-+
-+      /* get actual date */
-+      t = time(NULL);
-+      creatime = gmtime(&t);
++        char    error[LINE_LENGTH];
 +
-+      bzero(f1->DS1DSNAM, sizeof(f1->DS1DSNAM));
-+      sprintf(str, "PART    .NEW                                ");
-+      vtoc_ebcdic_enc(str, str, 44);
-+      strncpy(f1->DS1DSNAM, str, 44);
-+      f1->DS1FMTID = 0xf1;
-+      strncpy(f1->DS1DSSN, "      ", 6);
-+      f1->DS1VOLSQ = 0x0001;
++      switch (why) 
++      {
++      case unable_to_open:
++              sprintf(error, _("%s opening device '%s' failed.\n%s\n"),
++                      VTOC_ERROR, s1, s2);
++              break;
++      case unable_to_seek:
++              sprintf(error, _("%s seeking device '%s' failed.\n%s\n"),
++                      VTOC_ERROR, s1, s2);
++              break;
++      case unable_to_write:
++              sprintf(error, _("%s writing to device '%s' failed,\n%s\n"),
++                      VTOC_ERROR, s1, s2);
++              break;
++      case unable_to_read:
++              sprintf(error, _("%s reading from device '%s' failed.\n%s\n"),
++                      VTOC_ERROR, s1, s2);
++              break;
++      default: sprintf(error, _("Fatal error\n"));
++      }
 +
-+      vtoc_set_date(&f1->DS1CREDT,
-+                      (u_int8_t) creatime->tm_year,
-+                    (u_int16_t) creatime->tm_yday);
-+      /* expires never - 99 365 */
-+        vtoc_set_date(&f1->DS1EXPDT,
-+                    0x63,
-+                      0x016D);
-+      f1->DS1NOEPV = 0x01;
-+      f1->DS1NOBDB = 0x00;
-+        f1->DS1FLAG1 = 0x00;
-+      vtoc_ebcdic_enc("IBM LINUX    ", str, 13);
-+      strncpy(f1->DS1SYSCD, str, 13);
-+        vtoc_set_date(&f1->DS1REFD,
-+                    (u_int8_t) creatime->tm_year,
-+                      (u_int16_t) creatime->tm_yday);
-+        f1->DS1SMSFG = 0x00;
-+        f1->DS1SCXTF = 0x00;
-+        f1->DS1SCXTV = 0x0000;
-+        f1->DS1DSRG1 = 0x00;
-+        f1->DS1DSRG2 = 0x00;
-+        f1->DS1RECFM = 0x88;
-+        f1->DS1OPTCD = 0x00;
-+        f1->DS1BLKL  = blksize;
-+        f1->DS1LRECL = blksize;
-+        f1->DS1KEYL  = 0x00;
-+        f1->DS1RKP   = 0x0000;
-+        f1->DS1DSIND = 0x80; /* last volume for this dataset */
-+        f1->DS1SCAL1 = 0x80;
-+        bzero(&f1->DS1SCAL3, sizeof(f1->DS1SCAL3));
-+      vtoc_set_ttr(&f1->DS1LSTAR,
-+                   0x0000,
-+                   0x00);
-+      f1->DS1TRBAL = 0x00;
-+      bzero(&f1->res1, sizeof(f1->res1));
-+        memcpy(&f1->DS1EXT1,
-+               part_extent,
-+               sizeof(extent_t));
-+        bzero(&f1->DS1EXT2, sizeof(extent_t));
-+        bzero(&f1->DS1EXT3, sizeof(extent_t));
-+        vtoc_set_cchhb(&f1->DS1PTRDS,
-+                       0x0000, 0x0000, 0x00);
++        ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, error);
 +}
 +
 +
 +/*
-+ * do some updates to the VTOC format4 label
++ *
 + */
-+void 
-+vtoc_update_format4_label (
-+      format4_label_t *f4,
-+      cchhb_t *highest_f1,
-+      u_int16_t unused_update) 
++char * 
++vtoc_ebcdic_enc (char source[LINE_LENGTH],
++               char target[LINE_LENGTH],
++               int l) 
 +{
 +      PDEBUG
-+      /* update highest address of a format 1 label */
-+      memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
++        int i;
 +
-+      /* update unused DSCB count */
-+      f4->DS4DSREC = unused_update;
++      for (i = 0; i < l; i++) 
++              target[i]=ASCtoEBC[(unsigned char)(source[i])];
++
++      return target;
 +}
 +
 +
 +/*
-+ * reorganizes all extents within a FMT5 label
++ *
 + */
-+static void
-+vtoc_reorganize_FMT5_extents (format5_label_t *f5) 
++char * 
++vtoc_ebcdic_dec (char source[LINE_LENGTH],
++               char target[LINE_LENGTH],
++               int l) 
 +{
 +      PDEBUG
-+      ds5ext_t *ext, *last, tmp;
-+      int i, j;
++        int i;
 +
-+      for (i=0; i<26; i++)
-+      {
-+              if (i==0) 
-+                      last = &f5->DS5AVEXT; 
-+              else if ((i > 0) && (i < 8))
-+                      last = &f5->DS5EXTAV[i-1];
-+              else
-+                      last = &f5->DS5MAVET[i-8];
++      for (i = 0; i < l; i++) 
++              target[i]=EBCtoASC[(unsigned char)(source[i])];
 +
-+              for (j=i; j<26; j++)
-+              {
-+                      if (j==0) 
-+                              ext = &f5->DS5AVEXT; 
-+                      else if ((j > 0) && (j < 8))
-+                              ext = &f5->DS5EXTAV[j-1];
-+                      else
-+                              ext = &f5->DS5MAVET[j-8];
++      return target;
++}
 +
-+                      if (((ext->t > 0) && (last->t == 0)) || 
-+                          ((ext->t > 0) && (ext->t < last->t)))
-+                      {
-+                              tmp.t  = last->t;
-+                              tmp.fc = last->fc;
-+                              tmp.ft = last->ft;
-+                              last->t  = ext->t;
-+                              last->fc = ext->fc;
-+                              last->ft = ext->ft;
-+                              ext->t  = tmp.t;
-+                              ext->fc = tmp.fc;
-+                              ext->ft = tmp.ft;
-+                      }
-+              }
-+      }
++
++/*
++ *
++ */
++void 
++vtoc_set_extent (extent_t *ext,
++               u_int8_t typeind,
++               u_int8_t seqno,
++               cchh_t *lower,
++               cchh_t *upper) 
++{ 
++      PDEBUG
++        ext->typeind = typeind;
++        ext->seqno   = seqno;
++        memcpy(&ext->llimit,lower,sizeof(cchh_t));
++        memcpy(&ext->ulimit,upper,sizeof(cchh_t));
 +}
 +
 +
 +/*
-+ * add a free space extent description to the VTOC FMT5 DSCB
++ *
 + */
 +void 
-+vtoc_update_format5_label_add (format5_label_t *f5,
-+                             int verbose,
-+                             int cyl,
-+                             int trk,
-+                             u_int16_t a, 
-+                             u_int16_t b, 
-+                             u_int8_t c) 
++vtoc_set_cchh (cchh_t *addr,
++               u_int16_t cc,
++               u_int16_t hh) 
 +{
 +      PDEBUG
-+      ds5ext_t *ext = NULL, *tmp = NULL;
-+      int i;  
++        addr->cc = cc;
++      addr->hh = hh;
++}
 +
-+      for (i=0; i<26; i++)
-+      {
-+              if (i==0) 
-+                      ext = &f5->DS5AVEXT; 
-+              else if ((i > 0) && (i < 8))
-+                      ext = &f5->DS5EXTAV[i-1];
-+              else
-+                      ext = &f5->DS5MAVET[i-8];
 +
-+              if (((a < ext->t) && (a + b*trk + c > ext->t)) || 
-+                  ((a > ext->t) && (ext->t + ext->fc*trk + ext->ft > a)))
-+              {
-+                      printf("BUG: overlapping free space extents " \
-+                             "in FMT5 DSCB!\nexiting...\n");
-+                      exit(1);
-+              }
++/*
++ *
++ */
++static void 
++vtoc_set_ttr (ttr_t *addr,
++              u_int16_t tt,
++              u_int8_t r) 
++{
++      PDEBUG
++        addr->tt = tt;
++      addr->r = r;
++}
 +
-+              if ((ext->t + ext->fc + ext->ft) == 0x0000)
-+              {
-+                      ext->t  = a;
-+                      ext->fc = b;
-+                      ext->ft = c;
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT5 add extent: " \
-+                                     "add new extent\n");
-+                      break;
-+              }
-+      }
 +
-+      if (tmp == NULL)
-+      {
-+              /* BUG: no free extent found */
-+              printf("BUG: no free FMT5 DSCB extent found!\nexiting...\n");
-+              exit(1);
-+      }
++/*
++ *
++ */
++void 
++vtoc_set_cchhb (cchhb_t *addr,
++              u_int16_t cc,
++              u_int16_t hh,
++              u_int8_t b) 
++{
++      PDEBUG
++        addr->cc = cc;
++        addr->hh = hh;
++        addr->b = b;
++}
 +
-+      for (i=0; i<26; i++)
-+      {
-+              if (i==0)
-+                      ext = &f5->DS5AVEXT;
-+              else if ((i > 0) && (i < 8))
-+                      ext = &f5->DS5EXTAV[i-1];
-+              else
-+                      ext = &f5->DS5MAVET[i-8];
 +
-+              if ((ext->t + ext->fc + ext->ft) == 0x0000)
-+                      continue;
++/*
++ *
++ */
++void 
++vtoc_set_date (
++        labeldate_t * d,
++      u_int8_t year,
++      u_int16_t day) 
++{
++      PDEBUG
++        d->year = year;
++        d->day = day;
++}
 +
-+              if ((ext->t + ext->fc*trk + ext->ft) == tmp->t)
-+              {
-+                      /* this extent precedes the new one */
-+                      ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
-+                      ext->ft = (tmp->ft + ext->ft) % trk;
-+                      bzero(tmp, sizeof(ds5ext_t));
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT5 add extent: " \
-+                                     "merge with predecessor\n");
-+                      i = -1;
-+                      continue;
-+              } 
 +
-+              if ((tmp->t + tmp->fc*trk + tmp->ft) == ext->t)
-+              {
-+                      /* this extent succeeds the new one */
-+                      ext->t = tmp->t;
-+                      ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
-+                      ext->ft = (tmp->ft + ext->ft) % trk;
-+                      bzero(tmp, sizeof(ds5ext_t));
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT5 add extent: " \
-+                                     "merge with successor\n");
-+                      i = -1;
-+                      continue;
-+              } 
-+      }
++/*
++ * initializes the volume label with EBCDIC spaces
++ */
++void
++vtoc_volume_label_init (volume_label_t *vlabel)
++{
++      PDEBUG
++      sprintf(buffer, "%84s", " ");
++      vtoc_ebcdic_enc(buffer, buffer, 84);    
++      strncpy(vlabel->volkey, buffer, 84);
 +}
 +
 +
 +/*
-+ * remove a free space extent description from the VTOC FMT5 DSCB
++ * reads the volume label from dasd
 + */
-+void 
-+vtoc_update_format5_label_del (format5_label_t *f5,
-+                             int verbose,
-+                             int cyl,
-+                             int trk,
-+                             u_int16_t a,
-+                             u_int16_t b,
-+                             u_int8_t c) 
++int 
++vtoc_read_volume_label (
++        int f,
++        unsigned long vlabel_start,
++        volume_label_t *vlabel) 
 +{
 +      PDEBUG
-+      ds5ext_t *ext;
-+      int i, counter=0;
-+      
-+      for (i=0; i<26; i++)
++      int rc;
++
++      if (lseek(f, vlabel_start, SEEK_SET) == -1) 
 +      {
-+              if (i==0) 
-+                      ext = &f5->DS5AVEXT; 
-+              else if ((i > 0) && (i < 8))
-+                      ext = &f5->DS5EXTAV[i-1];
-+              else
-+                      ext = &f5->DS5MAVET[i-8];
++              vtoc_error(unable_to_seek, "vtoc_read_volume_label",
++                         "Could not read volume label.");
++              return 1;
++      }
 +
-+              if ((a == ext->t) && (b == ext->fc) && (c == ext->ft))
-+              {
-+                      /* fills up whole free space gap */
-+                      bzero(ext, sizeof(ds5ext_t));
-+                      if (verbose) 
-+                              printf("FMT5 del extent: fills whole gap\n");
-+                      counter++;
-+                      break;
-+              }
++      rc = read(f, vlabel, sizeof(volume_label_t));
++      if (rc != sizeof(volume_label_t)) 
++      {
++              vtoc_error(unable_to_read, "vtoc_read_volume_label",
++                         "Could not read volume label.");
++              return 1;
++      }
 +
-+              if ((a == ext->t) && ((b < ext->fc) || (c < ext->ft)))
-+              {
-+                      /* left-bounded in free space gap */
-+                      ext->t = ext->t + b*trk + c;
-+                      if (c > ext->ft)
-+                      {
-+                              ext->fc -= (b + 1);
-+                              ext->ft -= (c - trk);
-+                      }
-+                      else
-+                      {
-+                              ext->fc -= b;
-+                              ext->ft -= c;
-+                      }
-+                      if (verbose) 
-+                              printf("FMT5 del extent: left bounded\n");
-+                      counter++;
-+                      break;
-+              }
-+
-+              if ((ext->t < a) && 
-+                  ((ext->t + ext->fc*trk + ext->ft) == (a + b*trk + c)))
-+              {
-+                      /* right-bounded in free space gap */
-+                      if (c > ext->ft)
-+                      {
-+                              ext->fc -= (b + 1);
-+                              ext->ft -= (c - trk);
-+                      }
-+                      else
-+                      {
-+                              ext->fc -= b;
-+                              ext->ft -= c;
-+                      }
-+                      if (verbose) 
-+                              printf("FMT5 del extent: right bounded\n");
-+                      counter++;
-+                      break;
-+              }
-+
-+              if ((a > ext->t) &&
-+                      ((ext->t + ext->fc*trk + ext->ft) > (a + b*trk + c)))
-+              {
-+                      /* partition devides free space into 2 pieces */
-+                      u_int16_t x = a + b*trk + c;
-+                      u_int16_t w,y;
-+                      u_int8_t z;
-+
-+                      w = (ext->t + ext->fc*trk + ext->ft) - (a + b*trk + c);
-+                      y = w / trk;
-+                      z = w % trk;
-+
-+                      ext->fc = (a - ext->t) / trk;
-+                      ext->ft = (a - ext->t) % trk;
-+
-+                      vtoc_update_format5_label_add(f5, verbose, 
-+                                                    cyl, trk, x, y, z);
-+
-+                      if (verbose) 
-+                              printf("FMT5 del extent: 2 pieces\n");
-+                      counter++;
-+                      break;
-+              }
-+
-+              if ((a < ext->t) && (a + b*trk + c > ext->t) &&
-+                  (a + b*trk + c < ext->t + ext->fc*trk + ext->ft))
-+              {
-+                      printf("BUG: corresponding free space extent " \
-+                             "doesn't match free space currently shown " \
-+                             "in FMT5 DSCB!\nexiting...\n");
-+                      exit(1);
-+              }
-+              
-+              if ((a > ext->t) && (a < ext->t + ext->fc*trk + ext->ft) && 
-+                  (a + b*trk + c > ext->t + ext->fc*trk + ext->ft))
-+              {
-+                      printf("BUG: specified free space extent for " \
-+                             "deleting doesn't match free space " \
-+                             "currently shown in FMT5 DSCB!\n" \
-+                             "exiting...\n");
-+                      exit(1);
-+              }
-+      }
-+
-+      if (counter > 0) return;
-+
-+      printf("BUG: specified free space extent for " \
-+             "deleting not found in FMT5 DSCB!\n" \
-+             "exiting...\n");
-+      exit(1);
++      return 0;
 +}
 +
 +
 +/*
-+ * reorganizes all extents within a FMT7 label
++ * writes the volume label to dasd
 + */
-+static void
-+vtoc_reorganize_FMT7_extents (format7_label_t *f7) 
++int 
++vtoc_write_volume_label (
++        int f,
++      unsigned long vlabel_start,
++      volume_label_t *vlabel) 
 +{
 +      PDEBUG
-+      ds7ext_t *ext, *last, tmp;
-+      int i, j;
++        int rc;
 +
-+      for (i=0; i<16; i++)
++      if (lseek(f, vlabel_start, SEEK_SET) == -1) 
 +      {
-+              if (i<5) 
-+                      last = &f7->DS7EXTNT[i]; 
-+              else 
-+                      last = &f7->DS7ADEXT[i-5];
-+
-+              for (j=i; j<16; j++)
-+              {
-+                      if (j<5) 
-+                              ext = &f7->DS7EXTNT[j]; 
-+                      else 
-+                              ext = &f7->DS7ADEXT[j-5];
++              vtoc_error(unable_to_seek, "vtoc_write_volume_label",
++                         "Could not write volume label.");
++      }
 +
-+                      if (((ext->a > 0) && (last->a == 0)) || 
-+                          ((ext->a > 0) && (ext->a < last->a)))
-+                      {
-+                              tmp.a = last->a;
-+                              tmp.b = last->b;
-+                              last->a = ext->a;
-+                              last->b = ext->b;
-+                              ext->a = tmp.a;
-+                              ext->b = tmp.b;
-+                      }
-+              }
++      rc = write(f, vlabel, sizeof(volume_label_t)); 
++      if (rc != sizeof(volume_label_t)) 
++      {
++              vtoc_error(unable_to_write, "vtoc_write_volume_label",
++                         "Could not write volume label.");
 +      }
++      return 0;
 +}
 +
 +
 +/*
-+ * add a free space extent description to the VTOC FMT7 DSCB
++ * takes a string as input, converts it to uppercase, translates
++ * it to EBCDIC and fills it up with spaces before it copies it
++ * as volume serial to the volume label
 + */
-+void 
-+vtoc_update_format7_label_add (format7_label_t *f7, int verbose, 
-+                             u_int32_t a, u_int32_t b) 
++void
++vtoc_volume_label_set_volser (
++      volume_label_t *vlabel, 
++      char *volser)
 +{
 +      PDEBUG
-+      ds7ext_t *ext = NULL, *tmp = NULL;
-+      int i;  
++      int j, i = strlen(volser);
++      char s[VOLSER_LENGTH + 1];
 +
-+      for (i=0; i<16; i++)
-+      {
-+              if (i<5) 
-+                      ext = &f7->DS7EXTNT[i]; 
-+              else 
-+                      ext = &f7->DS7ADEXT[i-5];
++      strcpy(s, "      ");
++      vtoc_ebcdic_enc(s, s, VOLSER_LENGTH);
++      strncpy(vlabel->volid, s, VOLSER_LENGTH);
 +
-+              if (((a < ext->a) && (b > ext->a) && (b < ext->b)) || 
-+                  ((a > ext->a) && (a < ext->b) && (b > ext->b)))
-+              {
-+                      printf("BUG: overlapping free space extents " \
-+                             "in FMT7 DSCB!\nexiting...\n");
-+                      exit(1);
-+              }
++      if (i > VOLSER_LENGTH) i = VOLSER_LENGTH;
 +
-+              if ((ext->a + ext->b) == 0x00000000)
-+              {
-+                      ext->a = a;
-+                      ext->b = b;
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "add new extent\n");
-+                      break;
-+              }
++      strncpy(s, volser, i);
++      for (j=0; j<i; j++) {
++              s[j] = toupper(s[j]);
 +      }
 +
-+      if (tmp == NULL)
-+      {
-+              /* BUG: no free extent found */
-+              printf("BUG: no free FMT7 DSCB extent found!\nexiting...\n");
-+              exit(1);
-+      }
++      s[VOLSER_LENGTH] = 0x00;
++      vtoc_ebcdic_enc(s, s, i);
++      strncpy(vlabel->volid, s, i);
 +
-+      for (i=0; i<16; i++)
-+      {
-+              if (i<5) 
-+                      ext = &f7->DS7EXTNT[i]; 
-+              else 
-+                      ext = &f7->DS7ADEXT[i-5];
++      return;
++}
 +
-+              if ((ext->a + ext->b) == 0x00000000)
-+                      continue;
 +
-+              if ((ext->b + 1) == tmp->a)
-+              {
-+                      /* this extent precedes the new one */
-+                      ext->b = tmp->b;
-+                      bzero(tmp, sizeof(ds7ext_t));
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "merge with predecessor\n");
-+                      i = -1;
-+                      continue;
-+              } 
++/*
++ * returns the volume serial number right after it is translated 
++ * to ASCII
++ */
++char *
++vtoc_volume_label_get_volser (
++      volume_label_t *vlabel,
++      char *volser)
++{
++      PDEBUG
++      vtoc_ebcdic_dec(vlabel->volid, volser, VOLSER_LENGTH);
 +
-+              if (ext->a == (tmp->b + 1))
-+              {
-+                      /* this extent succeeds the new one */
-+                      ext->a = tmp->a;
-+                      bzero(tmp, sizeof(ds7ext_t));
-+                      tmp = ext;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "merge with successor\n");
-+                      i = -1;
-+                      continue;
-+              } 
-+      }
++      return volser;
 +}
 +
 +
 +/*
-+ * remove a free space extent description from the VTOC FMT7 DSCB
++ * sets the volume label key right after
++ * it has been translated to EBCDIC
 + */
-+void 
-+vtoc_update_format7_label_del (format7_label_t *f7, int verbose, 
-+                             u_int32_t a, u_int32_t b) 
++void
++vtoc_volume_label_set_key (
++        volume_label_t *vlabel,
++        char *key)
 +{
 +      PDEBUG
-+      ds7ext_t *ext;
-+      int i, counter=0;
-+      
-+      for (i=0; i<16; i++)
-+      {
-+              if (i<5) 
-+                      ext = &f7->DS7EXTNT[i]; 
-+              else 
-+                      ext = &f7->DS7ADEXT[i-5];
++        char s[4];
++ 
++        vtoc_ebcdic_enc(key, s, 4);
++        strncpy(vlabel->volkey, s, 4);
++ 
++        return;
++}                
 +
-+              if ((a == ext->a) && (b == ext->b))
-+              {
-+                      /* fills up whole free space gap */
-+                      bzero(ext, sizeof(ds7ext_t));
-+                      if (verbose) 
-+                              printf("FMT7 del extent: " \
-+                                     "fills whole gap\n");
-+                      counter++;
-+                      break;
-+              }
 +
-+              if ((a == ext->a) && (b < ext->b))
-+              {
-+                      /* left-bounded in free space gap */
-+                      ext->a = b + 1;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "left-bounded\n");
-+                      counter++;
-+                      break;
-+              }
++/*
++ * sets the volume label identifier right
++ * after it has been translated to EBCDIC
++ */
++void
++vtoc_volume_label_set_label (
++      volume_label_t *vlabel,
++      char *lbl)
++{
++      PDEBUG
++      char s[4];
 +
-+              if ((a > ext->a) && (b == ext->b))
-+              {
-+                      /* right-bounded in free space gap */
-+                      ext->b = a - 1;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "right-bounded\n");
-+                      counter++;
-+                      break;
-+              }
++      vtoc_ebcdic_enc(lbl, s, 4);
++      strncpy(vlabel->vollbl, s, 4);
 +
-+              if ((a > ext->a) && (b < ext->b))
-+              {
-+                      /* partition devides free space into 2 pieces */
-+                      vtoc_update_format7_label_add(f7, verbose, 
-+                                                    b+1, ext->b);
-+                      ext->b = a - 1;
-+                      if (verbose) 
-+                              printf("FMT7 add extent: " \
-+                                     "2 pieces\n");
-+                      counter++;
-+                      break;
-+              }
++      return;
++}
 +
-+              if (((a < ext->a) && (b > ext->a)) || ((a < ext->b) && (b > ext->b)))
-+              {
-+                      printf ("BUG: specified free space extent for deleting "
-+                              "doesn't match free space currently shown in "
-+                              "FMT7 DSCB!\nexiting...\n");
-+                      printf ("%d %d %d %d\n", a, b, ext->a, ext->b);
-+                      exit(1);
-+              }
-+      }
 +
-+      if (counter > 0) return;
++/*
++ * returns the volume label key = the label identifier
++ * right after it has been translated to ASCII
++ */
++char *
++vtoc_volume_label_get_label (
++      volume_label_t *vlabel,
++      char *lbl)
++{
++      PDEBUG
++      vtoc_ebcdic_dec(vlabel->vollbl, lbl, 4);
 +
-+      printf("BUG: specified free space extent for " \
-+             "deleting not found in FMT7 DSCB!\n" \
-+             "exiting...\n");
-+      exit(1);
++      return lbl;
 +}
 +
 +
 +/*
-+ *
++ * reads either a format4 label or a format1 label
++ * from the specified position
 + */
-+void
-+vtoc_set_freespace(format4_label_t *f4,
-+                 format5_label_t *f5,
-+                 format7_label_t *f7,
-+                 char ch,
-+                 int verbose,
-+                 u_int32_t start,
-+                 u_int32_t stop,
-+                 int cyl,
-+                 int trk)
-+{
++void 
++vtoc_read_label (int f,
++               unsigned long position,
++               format1_label_t *f1,
++               format4_label_t *f4,
++               format5_label_t *f5,
++               format7_label_t *f7) 
++{        
 +      PDEBUG
-+      if ((cyl * trk) > BIG_DISK_SIZE)
++      int t;
++
++        if (lseek(f, position, SEEK_SET) == -1) 
 +      {
-+              if (ch == '+')
++              vtoc_error(unable_to_seek, "vtoc_read_label",
++                         _("Could not read VTOC labels."));
++        }
++
++      if (f1 != NULL)
++      {
++              t = sizeof(format1_label_t);
++              if (read(f, f1, t) != t) 
 +              {
-+                      vtoc_update_format7_label_add(f7, verbose, 
-+                                                    start, stop);
++                      vtoc_error(unable_to_read, "vtoc_read_label",
++                                 _("Could not read VTOC FMT1 DSCB."));
 +              }
-+              else if (ch == '-')
++      }
++
++      if (f4 != NULL)
++      {
++              t = sizeof(format4_label_t);
++              if (read(f, f4, t) != t) 
 +              {
-+                      vtoc_update_format7_label_del(f7, verbose, 
-+                                                    start, stop);
++                      vtoc_error(unable_to_read, "vtoc_read_label",
++                                 _("Could not read VTOC FMT4 DSCB."));
 +              }
-+              else
++      }
++
++        if (f5 != NULL)
++      {
++              t = sizeof(format5_label_t);
++                if (read(f, f5, t) != t)
++                {
++                        vtoc_error(unable_to_read, "vtoc_read_label",
++                                   _("Could not read VTOC FMT5 DSCB."));
++                }
++      }
++
++      if (f7 != NULL)
++      {
++              t = sizeof(format7_label_t);
++              if (read(f, f7, t) != t) 
 +              {
-+                      printf("BUG: syntax error in " \
-+                             "vtoc_set_freespace call\n");
++                      vtoc_error(unable_to_read, "vtoc_read_label",
++                                 _("Could not read VTOC FMT7 DSCB."));
 +              }
++      }
++}
 +
-+              vtoc_reorganize_FMT7_extents (f7);
 +
-+              f4->DS4VTOCI = 0xa0;
-+              f4->DS4EFLVL = 0x07;
-+              vtoc_set_cchhb(&f4->DS4EFPTR, 0x0000, 0x0001, 0x03);
-+      }
-+      else
++/*
++ * writes either a FMT1, FMT4 or FMT5 label
++ * to the specified position
++ */
++void
++vtoc_write_label (int f,
++                unsigned long position,
++                format1_label_t *f1, 
++                format4_label_t *f4,
++                format5_label_t *f5,
++                format7_label_t *f7)
++{
++      PDEBUG
++      int t;
++
++        if (lseek(f, position, SEEK_SET) == -1) 
 +      {
-+              u_int16_t x,y;
-+              u_int8_t z;
++              vtoc_error(unable_to_seek, "vtoc_write_label",
++                         _("Could not write VTOC labels."));
++        }
 +
-+              x = (u_int16_t) start;
-+              y = (u_int16_t) ((stop - start + 1) / trk);
-+              z =  (u_int8_t) ((stop - start + 1) % trk);
++      if (f1 != NULL)
++      {
++              t = sizeof(format1_label_t);
++              if (write(f, f1, t) != t) 
++              {
++                      vtoc_error(unable_to_write, "vtoc_write_label",
++                                 _("Could not write VTOC FMT1 DSCB."));
++              }
++      }
 +
-+              if (ch == '+')
++      if (f4 != NULL)
++      {
++              t = sizeof(format4_label_t);
++              if (write(f, f4, t) != t) 
 +              {
-+                      vtoc_update_format5_label_add(f5, verbose,
-+                                                    cyl, trk,
-+                                                    x, y, z);
++                      vtoc_error(unable_to_write, "vtoc_write_label",
++                                 _("Could not write VTOC FMT4 DSCB."));
 +              }
-+              else if (ch == '-')
++      }
++
++      if (f5 != NULL)
++      {
++              t = sizeof(format5_label_t);
++              if (write(f, f5, t) != t) 
 +              {
-+                      vtoc_update_format5_label_del(f5, verbose, 
-+                                                    cyl, trk,
-+                                                    x, y, z);
++                      vtoc_error(unable_to_write, "vtoc_write_label",
++                                 _("Could not write VTOC FMT5 DSCB."));
 +              }
-+              else
++      }
++
++      if (f7 != NULL)
++      {
++              t = sizeof(format7_label_t);
++              if (write(f, f7, t) != t) 
 +              {
-+                      printf("BUG: syntax error in " \
-+                             "vtoc_set_freespace call\n");
++                      vtoc_error(unable_to_write, "vtoc_write_label",
++                                 _("Could not write VTOC FMT7 DSCB."));
 +              }
-+              vtoc_reorganize_FMT5_extents (f5);
 +      }
-+              
-+}
 +
++}
 +
 +
++/*
++ * initializes a format4 label
++ */
++void 
++vtoc_init_format4_label (
++      format4_label_t    *f4,
++      unsigned int usable_partitions,
++      unsigned int cylinders,
++      unsigned int tracks,
++      unsigned int blocks,
++      unsigned int blksize,
++      u_int16_t dev_type) 
++{
++      PDEBUG
++      int i;
 +
++      cchh_t lower = {VTOC_START_CC, VTOC_START_HH};
++      cchh_t upper = {VTOC_START_CC, VTOC_START_HH};
 +
++      for (i=0; i<44; i++) f4->DS4KEYCD[i] = 0x04;
++        f4->DS4IDFMT = 0xf4;
++      vtoc_set_cchhb(&f4->DS4HPCHR, 0x0000, 0x0000, 0x00);
++        f4->DS4DSREC = blocks - 2;
++      /* free space starts right behind VTOC
++         vtoc_set_cchh(&f4->DS4HCCHH, VTOC_START_CC, VTOC_START_HH + 1);*/
++        vtoc_set_cchh(&f4->DS4HCCHH, 0x0000, 0x0000);
++        f4->DS4NOATK = 0x0000;
++        f4->DS4VTOCI = 0x00;
++        f4->DS4NOEXT = 0x01;
++        f4->DS4SMSFG = 0x00;
++        f4->DS4DEVAC = 0x00;
 +
++        /* -- begin f4->DS4DEVCT -- */
++        f4->DS4DEVCT.DS4DSCYL = cylinders;
++        f4->DS4DEVCT.DS4DSTRK = tracks;
 +
++      switch (dev_type)
++      {
++      case DASD_3380_TYPE:
++              f4->DS4DEVCT.DS4DEVTK = DASD_3380_VALUE;
++              break;
++      case DASD_3390_TYPE:
++              f4->DS4DEVCT.DS4DEVTK = DASD_3390_VALUE;
++              break;
++      case DASD_9345_TYPE:
++              f4->DS4DEVCT.DS4DEVTK = DASD_9345_VALUE;
++              break;
++        default:
++              f4->DS4DEVCT.DS4DEVTK = blocks * blksize;;
++        }
++
++
++        f4->DS4DEVCT.DS4DEVI  = 0x00;
++        f4->DS4DEVCT.DS4DEVL  = 0x00;
++        f4->DS4DEVCT.DS4DEVK  = 0x00;
++        f4->DS4DEVCT.DS4DEVFG = 0x30;
++        f4->DS4DEVCT.DS4DEVTL = 0x0000;
++        f4->DS4DEVCT.DS4DEVDT = blocks;
++        f4->DS4DEVCT.DS4DEVDB = 0x00;
++        /* -- end f4->DS4DEVCT -- */
++
++      bzero(f4->DS4AMTIM, sizeof(f4->DS4AMTIM));
++      bzero(f4->DS4AMCAT, sizeof(f4->DS4AMCAT));
++      bzero(f4->DS4R2TIM, sizeof(f4->DS4R2TIM));
++      bzero(f4->res1, sizeof(f4->res1));
++      bzero(f4->DS4F6PTR, sizeof(f4->DS4F6PTR));
++
++        /* -- begin f4lbl->DS4VTOCE -- */
++      vtoc_set_extent(&f4->DS4VTOCE, 0x01, 0x00, &lower, &upper);
++        /* -- end f4lbl->DS4VTOCE -- */
++
++      bzero(f4->res2, sizeof(f4->res2));
++      f4->DS4EFLVL = 0x00;
++      bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
++      bzero(f4->res3, sizeof(f4->res3));
++}
 +
 +
-diff -ruN --minimal parted-1.6.21.orig/libparted/vtoc.h parted-1.6.21/libparted/vtoc.h
---- parted-1.6.21.orig/libparted/vtoc.h        1969-12-31 19:00:00.000000000 -0500
-+++ parted-1.6.21/libparted/vtoc.h     2005-01-21 15:00:40.455627637 -0500
-@@ -0,0 +1,371 @@
 +/*
-+ * File...........: s390-tools/dasdview/vtoc.h
-+ * Author(s)......: Horst Hummel <horst.hummel@de.ibm.com>
-+ * Bugreports.to..: <Linux390@de.ibm.com>
-+ *
-+ * This is a user-space copy of the kernel vtoc,h. 
-+ * 
-+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2002
-+ *
-+ * History of changes (starts March 2002)
-+ * 2002-03-12 initial
++ * initializes a format5 label
 + */
++void
++vtoc_init_format5_label (format5_label_t *f5) 
++{
++      PDEBUG
++      int i;
 +
-+#ifndef VTOC_H
-+#define VTOC_H
++      bzero(f5, sizeof(format5_label_t));
++      for (i=0; i<4; i++) f5->DS5KEYID[i] = 0x05;
++      f5->DS5FMTID = 0xf5;
++}
 +
-+#include <string.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <fcntl.h>
-+#include <unistd.h>
 +
-+#include <sys/stat.h>
-+#include <sys/ioctl.h>
++/*
++ * initializes a format7 label
++ */
++void
++vtoc_init_format7_label (format7_label_t *f7) 
++{
++      PDEBUG
++      int i;
 +
-+#define LINE_LENGTH 80
-+#define VTOC_START_CC 0x0
-+#define VTOC_START_HH 0x1
-+#define FIRST_USABLE_CYL 1
-+#define FIRST_USABLE_TRK 2
++      bzero(f7, sizeof(format7_label_t));
++      for (i=0; i<4; i++) f7->DS7KEYID[i] = 0x07;
++      f7->DS7FMTID = 0xf7;
++}
 +
-+#define DASD_3380_TYPE 13148
-+#define DASD_3390_TYPE 13200
-+#define DASD_9345_TYPE 37701
 +
-+#define DASD_3380_VALUE 0xbb60
-+#define DASD_3390_VALUE 0xe5a2
-+#define DASD_9345_VALUE 0xbc98
++/*
++ * initializes a format1 label
++ */
++void 
++vtoc_init_format1_label (
++      char *volid,
++        unsigned int blksize,
++      extent_t *part_extent,
++      format1_label_t *f1) 
++{
++      PDEBUG
++        struct tm * creatime;
++      time_t t;
++      char str[80];
 +
-+#define VOLSER_LENGTH 6
-+#define BIG_DISK_SIZE 0x10000
++      /* get actual date */
++      t = time(NULL);
++      creatime = gmtime(&t);
 +
-+#define VTOC_ERROR "VTOC error:"
++      bzero(f1->DS1DSNAM, sizeof(f1->DS1DSNAM));
++      sprintf(str, "PART    .NEW                                ");
++      vtoc_ebcdic_enc(str, str, 44);
++      strncpy(f1->DS1DSNAM, str, 44);
++      f1->DS1FMTID = 0xf1;
++      strncpy(f1->DS1DSSN, "      ", 6);
++      f1->DS1VOLSQ = 0x0001;
 +
++      vtoc_set_date(&f1->DS1CREDT,
++                      (u_int8_t) creatime->tm_year,
++                    (u_int16_t) creatime->tm_yday);
++      /* expires never - 99 365 */
++        vtoc_set_date(&f1->DS1EXPDT,
++                    0x63,
++                      0x016D);
++      f1->DS1NOEPV = 0x01;
++      f1->DS1NOBDB = 0x00;
++        f1->DS1FLAG1 = 0x00;
++      vtoc_ebcdic_enc("IBM LINUX    ", str, 13);
++      strncpy(f1->DS1SYSCD, str, 13);
++        vtoc_set_date(&f1->DS1REFD,
++                    (u_int8_t) creatime->tm_year,
++                      (u_int16_t) creatime->tm_yday);
++        f1->DS1SMSFG = 0x00;
++        f1->DS1SCXTF = 0x00;
++        f1->DS1SCXTV = 0x0000;
++        f1->DS1DSRG1 = 0x00;
++        f1->DS1DSRG2 = 0x00;
++        f1->DS1RECFM = 0x88;
++        f1->DS1OPTCD = 0x00;
++        f1->DS1BLKL  = blksize;
++        f1->DS1LRECL = blksize;
++        f1->DS1KEYL  = 0x00;
++        f1->DS1RKP   = 0x0000;
++        f1->DS1DSIND = 0x80; /* last volume for this dataset */
++        f1->DS1SCAL1 = 0x80;
++        bzero(&f1->DS1SCAL3, sizeof(f1->DS1SCAL3));
++      vtoc_set_ttr(&f1->DS1LSTAR,
++                   0x0000,
++                   0x00);
++      f1->DS1TRBAL = 0x00;
++      bzero(&f1->res1, sizeof(f1->res1));
++        memcpy(&f1->DS1EXT1,
++               part_extent,
++               sizeof(extent_t));
++        bzero(&f1->DS1EXT2, sizeof(extent_t));
++        bzero(&f1->DS1EXT3, sizeof(extent_t));
++        vtoc_set_cchhb(&f1->DS1PTRDS,
++                       0x0000, 0x0000, 0x00);
++}
 +
-+typedef struct ttr 
-+{
-+        u_int16_t tt;
-+        u_int8_t  r;
-+} __attribute__ ((packed)) ttr_t;
 +
-+typedef struct cchhb 
++/*
++ * do some updates to the VTOC format4 label
++ */
++void 
++vtoc_update_format4_label (
++      format4_label_t *f4,
++      cchhb_t *highest_f1,
++      u_int16_t unused_update) 
 +{
-+        u_int16_t cc;
-+        u_int16_t hh;
-+        u_int8_t b;
-+} __attribute__ ((packed)) cchhb_t;
++      PDEBUG
++      /* update highest address of a format 1 label */
++      memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
 +
-+typedef struct cchh 
-+{
-+        u_int16_t cc;
-+        u_int16_t hh;
-+} __attribute__ ((packed)) cchh_t;
++      /* update unused DSCB count */
++      f4->DS4DSREC = unused_update;
++}
 +
-+typedef struct labeldate 
++
++/*
++ * reorganizes all extents within a FMT5 label
++ */
++static void
++vtoc_reorganize_FMT5_extents (format5_label_t *f5) 
 +{
-+        u_int8_t  year;
-+        u_int16_t day;
-+} __attribute__ ((packed)) labeldate_t;
++      PDEBUG
++      ds5ext_t *ext, *last, tmp;
++      int i, j;
 +
++      for (i=0; i<26; i++)
++      {
++              if (i==0) 
++                      last = &f5->DS5AVEXT; 
++              else if ((i > 0) && (i < 8))
++                      last = &f5->DS5EXTAV[i-1];
++              else
++                      last = &f5->DS5MAVET[i-8];
 +
-+typedef struct volume_label 
-+{
-+        char volkey[4];         /* volume key = volume label                 */
-+      char vollbl[4];         /* volume label                              */
-+      char volid[6];          /* volume identifier                         */
-+      u_int8_t security;              /* security byte                             */
-+      cchhb_t vtoc;           /* VTOC address                              */
-+      char res1[5];           /* reserved                                  */
-+        char cisize[4];               /* CI-size for FBA,...                       */
-+                                /* ...blanks for CKD                         */
-+      char blkperci[4];       /* no of blocks per CI (FBA), blanks for CKD */
-+      char labperci[4];       /* no of labels per CI (FBA), blanks for CKD */
-+      char res2[4];           /* reserved                                  */
-+      char lvtoc[14];         /* owner code for LVTOC                      */
-+      char res3[29];          /* reserved                                  */
-+} __attribute__ ((packed)) volume_label_t;
++              for (j=i; j<26; j++)
++              {
++                      if (j==0) 
++                              ext = &f5->DS5AVEXT; 
++                      else if ((j > 0) && (j < 8))
++                              ext = &f5->DS5EXTAV[j-1];
++                      else
++                              ext = &f5->DS5MAVET[j-8];
++
++                      if (((ext->t > 0) && (last->t == 0)) || 
++                          ((ext->t > 0) && (ext->t < last->t)))
++                      {
++                              tmp.t  = last->t;
++                              tmp.fc = last->fc;
++                              tmp.ft = last->ft;
++                              last->t  = ext->t;
++                              last->fc = ext->fc;
++                              last->ft = ext->ft;
++                              ext->t  = tmp.t;
++                              ext->fc = tmp.fc;
++                              ext->ft = tmp.ft;
++                      }
++              }
++      }
++}
 +
 +
-+typedef struct extent 
++/*
++ * add a free space extent description to the VTOC FMT5 DSCB
++ */
++void 
++vtoc_update_format5_label_add (format5_label_t *f5,
++                             int verbose,
++                             int cyl,
++                             int trk,
++                             u_int16_t a, 
++                             u_int16_t b, 
++                             u_int8_t c) 
 +{
-+        u_int8_t  typeind;          /* extent type indicator                     */
-+        u_int8_t  seqno;            /* extent sequence number                    */
-+        cchh_t llimit;          /* starting point of this extent             */
-+        cchh_t ulimit;          /* ending point of this extent               */
-+} __attribute__ ((packed)) extent_t;
++      PDEBUG
++      ds5ext_t *ext = NULL, *tmp = NULL;
++      int i;  
++
++      for (i=0; i<26; i++)
++      {
++              if (i==0) 
++                      ext = &f5->DS5AVEXT; 
++              else if ((i > 0) && (i < 8))
++                      ext = &f5->DS5EXTAV[i-1];
++              else
++                      ext = &f5->DS5MAVET[i-8];
 +
++              if (((a < ext->t) && (a + b*trk + c > ext->t)) || 
++                  ((a > ext->t) && (ext->t + ext->fc*trk + ext->ft > a)))
++              {
++                      printf("BUG: overlapping free space extents " \
++                             "in FMT5 DSCB!\nexiting...\n");
++                      exit(1);
++              }
 +
-+typedef struct dev_const 
-+{
-+        u_int16_t DS4DSCYL;           /* number of logical cyls                  */
-+        u_int16_t DS4DSTRK;           /* number of tracks in a logical cylinder  */
-+        u_int16_t DS4DEVTK;           /* device track length                     */
-+        u_int8_t  DS4DEVI;            /* non-last keyed record overhead          */
-+        u_int8_t  DS4DEVL;            /* last keyed record overhead              */
-+        u_int8_t  DS4DEVK;            /* non-keyed record overhead differential  */
-+        u_int8_t  DS4DEVFG;           /* flag byte                               */
-+        u_int16_t DS4DEVTL;           /* device tolerance                        */
-+        u_int8_t  DS4DEVDT;           /* number of DSCB's per track              */
-+        u_int8_t  DS4DEVDB;           /* number of directory blocks per track    */
-+} __attribute__ ((packed)) dev_const_t;
++              if ((ext->t + ext->fc + ext->ft) == 0x0000)
++              {
++                      ext->t  = a;
++                      ext->fc = b;
++                      ext->ft = c;
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT5 add extent: " \
++                                     "add new extent\n");
++                      break;
++              }
++      }
 +
++      if (tmp == NULL)
++      {
++              /* BUG: no free extent found */
++              printf("BUG: no free FMT5 DSCB extent found!\nexiting...\n");
++              exit(1);
++      }
 +
-+typedef struct format1_label 
++      for (i=0; i<26; i++)
++      {
++              if (i==0)
++                      ext = &f5->DS5AVEXT;
++              else if ((i > 0) && (i < 8))
++                      ext = &f5->DS5EXTAV[i-1];
++              else
++                      ext = &f5->DS5MAVET[i-8];
++
++              if ((ext->t + ext->fc + ext->ft) == 0x0000)
++                      continue;
++
++              if ((ext->t + ext->fc*trk + ext->ft) == tmp->t)
++              {
++                      /* this extent precedes the new one */
++                      ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
++                      ext->ft = (tmp->ft + ext->ft) % trk;
++                      bzero(tmp, sizeof(ds5ext_t));
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT5 add extent: " \
++                                     "merge with predecessor\n");
++                      i = -1;
++                      continue;
++              } 
++
++              if ((tmp->t + tmp->fc*trk + tmp->ft) == ext->t)
++              {
++                      /* this extent succeeds the new one */
++                      ext->t = tmp->t;
++                      ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
++                      ext->ft = (tmp->ft + ext->ft) % trk;
++                      bzero(tmp, sizeof(ds5ext_t));
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT5 add extent: " \
++                                     "merge with successor\n");
++                      i = -1;
++                      continue;
++              } 
++      }
++}
++
++
++/*
++ * remove a free space extent description from the VTOC FMT5 DSCB
++ */
++void 
++vtoc_update_format5_label_del (format5_label_t *f5,
++                             int verbose,
++                             int cyl,
++                             int trk,
++                             u_int16_t a,
++                             u_int16_t b,
++                             u_int8_t c) 
 +{
-+      char  DS1DSNAM[44];       /* data set name                           */
-+      u_int8_t  DS1FMTID;           /* format identifier                       */
-+      char  DS1DSSN[6];         /* data set serial number                  */
-+      u_int16_t DS1VOLSQ;           /* volume sequence number                  */
-+      labeldate_t DS1CREDT;     /* creation date: ydd                      */
-+      labeldate_t DS1EXPDT;     /* expiration date                         */
-+      u_int8_t  DS1NOEPV;           /* number of extents on volume             */
-+        u_int8_t  DS1NOBDB;           /* no. of bytes used in last direction blk */
-+      u_int8_t  DS1FLAG1;           /* flag 1                                  */
-+      char  DS1SYSCD[13];       /* system code                             */
-+      labeldate_t DS1REFD;      /* date last referenced                    */
-+        u_int8_t  DS1SMSFG;           /* system managed storage indicators       */
-+        u_int8_t  DS1SCXTF;           /* sec. space extension flag byte          */
-+        u_int16_t DS1SCXTV;           /* secondary space extension value         */
-+        u_int8_t  DS1DSRG1;           /* data set organisation byte 1            */
-+        u_int8_t  DS1DSRG2;           /* data set organisation byte 2            */
-+      u_int8_t  DS1RECFM;           /* record format                           */
-+      u_int8_t  DS1OPTCD;           /* option code                             */
-+      u_int16_t DS1BLKL;            /* block length                            */
-+      u_int16_t DS1LRECL;           /* record length                           */
-+      u_int8_t  DS1KEYL;            /* key length                              */
-+      u_int16_t DS1RKP;             /* relative key position                   */
-+      u_int8_t  DS1DSIND;           /* data set indicators                     */
-+        u_int8_t  DS1SCAL1;           /* secondary allocation flag byte          */
-+      char DS1SCAL3[3];         /* secondary allocation quantity           */
-+      ttr_t DS1LSTAR;           /* last used track and block on track      */
-+      u_int16_t DS1TRBAL;           /* space remaining on last used track      */
-+        u_int16_t res1;               /* reserved                                */
-+      extent_t DS1EXT1;         /* first extent description                */
-+      extent_t DS1EXT2;         /* second extent description               */
-+      extent_t DS1EXT3;         /* third extent description                */
-+      cchhb_t DS1PTRDS;         /* possible pointer to f2 or f3 DSCB       */
-+} __attribute__ ((packed)) format1_label_t;
++      PDEBUG
++      ds5ext_t *ext;
++      int i, counter=0;
++      
++      for (i=0; i<26; i++)
++      {
++              if (i==0) 
++                      ext = &f5->DS5AVEXT; 
++              else if ((i > 0) && (i < 8))
++                      ext = &f5->DS5EXTAV[i-1];
++              else
++                      ext = &f5->DS5MAVET[i-8];
++
++              if ((a == ext->t) && (b == ext->fc) && (c == ext->ft))
++              {
++                      /* fills up whole free space gap */
++                      bzero(ext, sizeof(ds5ext_t));
++                      if (verbose) 
++                              printf("FMT5 del extent: fills whole gap\n");
++                      counter++;
++                      break;
++              }
++
++              if ((a == ext->t) && ((b < ext->fc) || (c < ext->ft)))
++              {
++                      /* left-bounded in free space gap */
++                      ext->t = ext->t + b*trk + c;
++                      if (c > ext->ft)
++                      {
++                              ext->fc -= (b + 1);
++                              ext->ft -= (c - trk);
++                      }
++                      else
++                      {
++                              ext->fc -= b;
++                              ext->ft -= c;
++                      }
++                      if (verbose) 
++                              printf("FMT5 del extent: left bounded\n");
++                      counter++;
++                      break;
++              }
++
++              if ((ext->t < a) && 
++                  ((ext->t + ext->fc*trk + ext->ft) == (a + b*trk + c)))
++              {
++                      /* right-bounded in free space gap */
++                      if (c > ext->ft)
++                      {
++                              ext->fc -= (b + 1);
++                              ext->ft -= (c - trk);
++                      }
++                      else
++                      {
++                              ext->fc -= b;
++                              ext->ft -= c;
++                      }
++                      if (verbose) 
++                              printf("FMT5 del extent: right bounded\n");
++                      counter++;
++                      break;
++              }
 +
++              if ((a > ext->t) &&
++                      ((ext->t + ext->fc*trk + ext->ft) > (a + b*trk + c)))
++              {
++                      /* partition devides free space into 2 pieces */
++                      u_int16_t x = a + b*trk + c;
++                      u_int16_t w,y;
++                      u_int8_t z;
 +
-+typedef struct format4_label 
-+{
-+      char  DS4KEYCD[44];       /* key code for VTOC labels: 44 times 0x04 */
-+        u_int8_t  DS4IDFMT;           /* format identifier                       */
-+      cchhb_t DS4HPCHR;         /* highest address of a format 1 DSCB      */
-+        u_int16_t DS4DSREC;           /* number of available DSCB's              */
-+        cchh_t DS4HCCHH;          /* CCHH of next available alternate track  */
-+        u_int16_t DS4NOATK;           /* number of remaining alternate tracks    */
-+        u_int8_t  DS4VTOCI;           /* VTOC indicators                         */
-+        u_int8_t  DS4NOEXT;           /* number of extents in VTOC               */
-+        u_int8_t  DS4SMSFG;           /* system managed storage indicators       */
-+        u_int8_t  DS4DEVAC;           /* number of alternate cylinders. 
-+                                     Subtract from first two bytes of 
-+                                     DS4DEVSZ to get number of usable
-+                                   cylinders. can be zero. valid
-+                                   only if DS4DEVAV on.                    */
-+        dev_const_t DS4DEVCT;     /* device constants                        */
-+        char DS4AMTIM[8];         /* VSAM time stamp                         */
-+        char DS4AMCAT[3];         /* VSAM catalog indicator                  */
-+        char DS4R2TIM[8];         /* VSAM volume/catalog match time stamp    */
-+        char res1[5];             /* reserved                                */
-+        char DS4F6PTR[5];         /* pointer to first format 6 DSCB          */
-+        extent_t DS4VTOCE;        /* VTOC extent description                 */
-+        char res2[10];            /* reserved                                */
-+        u_int8_t DS4EFLVL;            /* extended free-space management level    */
-+        cchhb_t DS4EFPTR;         /* pointer to extended free-space info     */
-+        char res3[9];             /* reserved                                */
-+} __attribute__ ((packed)) format4_label_t;
++                      w = (ext->t + ext->fc*trk + ext->ft) - (a + b*trk + c);
++                      y = w / trk;
++                      z = w % trk;
 +
++                      ext->fc = (a - ext->t) / trk;
++                      ext->ft = (a - ext->t) % trk;
 +
-+typedef struct ds5ext 
-+{
-+      u_int16_t t;                  /* RTA of the first track of free extent   */
-+      u_int16_t fc;                 /* number of whole cylinders in free ext.  */
-+      u_int8_t  ft;                 /* number of remaining free tracks         */
-+} __attribute__ ((packed)) ds5ext_t;
++                      vtoc_update_format5_label_add(f5, verbose, 
++                                                    cyl, trk, x, y, z);
 +
++                      if (verbose) 
++                              printf("FMT5 del extent: 2 pieces\n");
++                      counter++;
++                      break;
++              }
 +
-+typedef struct format5_label 
-+{
-+      char DS5KEYID[4];         /* key identifier                          */
-+      ds5ext_t DS5AVEXT;        /* first available (free-space) extent.    */
-+      ds5ext_t DS5EXTAV[7];     /* seven available extents                 */
-+      u_int8_t DS5FMTID;            /* format identifier                       */
-+      ds5ext_t DS5MAVET[18];    /* eighteen available extents              */
-+      cchhb_t DS5PTRDS;         /* pointer to next format5 DSCB            */
-+} __attribute__ ((packed)) format5_label_t;
++              if ((a < ext->t) && (a + b*trk + c > ext->t) &&
++                  (a + b*trk + c < ext->t + ext->fc*trk + ext->ft))
++              {
++                      printf("BUG: corresponding free space extent " \
++                             "doesn't match free space currently shown " \
++                             "in FMT5 DSCB!\nexiting...\n");
++                      exit(1);
++              }
++              
++              if ((a > ext->t) && (a < ext->t + ext->fc*trk + ext->ft) && 
++                  (a + b*trk + c > ext->t + ext->fc*trk + ext->ft))
++              {
++                      printf("BUG: specified free space extent for " \
++                             "deleting doesn't match free space " \
++                             "currently shown in FMT5 DSCB!\n" \
++                             "exiting...\n");
++                      exit(1);
++              }
++      }
 +
++      if (counter > 0) return;
 +
-+typedef struct ds7ext 
-+{
-+      u_int32_t a;                  /* starting RTA value                      */
-+      u_int32_t b;                  /* ending RTA value + 1                    */
-+} __attribute__ ((packed)) ds7ext_t;
++      printf("BUG: specified free space extent for " \
++             "deleting not found in FMT5 DSCB!\n" \
++             "exiting...\n");
++      exit(1);
++}
 +
 +
-+typedef struct format7_label 
++/*
++ * reorganizes all extents within a FMT7 label
++ */
++static void
++vtoc_reorganize_FMT7_extents (format7_label_t *f7) 
 +{
-+      char DS7KEYID[4];         /* key identifier                          */
-+      ds7ext_t DS7EXTNT[5];     /* space for 5 extent descriptions         */
-+      u_int8_t DS7FMTID;            /* format identifier                       */
-+      ds7ext_t DS7ADEXT[11];    /* space for 11 extent descriptions        */
-+      char res1[2];             /* reserved                                */
-+      cchhb_t DS7PTRDS;         /* pointer to next FMT7 DSCB               */
-+} __attribute__ ((packed)) format7_label_t;
++      PDEBUG
++      ds7ext_t *ext, *last, tmp;
++      int i, j;
 +
++      for (i=0; i<16; i++)
++      {
++              if (i<5) 
++                      last = &f7->DS7EXTNT[i]; 
++              else 
++                      last = &f7->DS7ADEXT[i-5];
 +
-+char * vtoc_ebcdic_enc (
-+        char source[LINE_LENGTH],
-+        char target[LINE_LENGTH],
-+      int l);
-+char * vtoc_ebcdic_dec (
-+        char source[LINE_LENGTH],
-+      char target[LINE_LENGTH],
-+      int l);
-+void vtoc_set_extent (
-+        extent_t * ext,
-+        u_int8_t typeind,
-+        u_int8_t seqno,
-+        cchh_t * lower,
-+        cchh_t * upper);
-+void vtoc_set_cchh (
-+        cchh_t * addr,
-+      u_int16_t cc,
-+      u_int16_t hh);
-+void vtoc_set_cchhb (
-+        cchhb_t * addr,
-+        u_int16_t cc,
-+        u_int16_t hh,
-+        u_int8_t b);
-+void vtoc_set_date (
-+        labeldate_t * d,
-+        u_int8_t year,
-+        u_int16_t day);
++              for (j=i; j<16; j++)
++              {
++                      if (j<5) 
++                              ext = &f7->DS7EXTNT[j]; 
++                      else 
++                              ext = &f7->DS7ADEXT[j-5];
 +
-+void vtoc_volume_label_init (
-+      volume_label_t *vlabel);
++                      if (((ext->a > 0) && (last->a == 0)) || 
++                          ((ext->a > 0) && (ext->a < last->a)))
++                      {
++                              tmp.a = last->a;
++                              tmp.b = last->b;
++                              last->a = ext->a;
++                              last->b = ext->b;
++                              ext->a = tmp.a;
++                              ext->b = tmp.b;
++                      }
++              }
++      }
++}
 +
-+int vtoc_read_volume_label (
-+        int fd,
-+        unsigned long vlabel_start,
-+        volume_label_t * vlabel);
 +
-+int vtoc_write_volume_label (
-+        int fd,
-+        unsigned long vlabel_start,
-+        volume_label_t *vlabel);
++/*
++ * add a free space extent description to the VTOC FMT7 DSCB
++ */
++void 
++vtoc_update_format7_label_add (format7_label_t *f7, int verbose, 
++                             u_int32_t a, u_int32_t b) 
++{
++      PDEBUG
++      ds7ext_t *ext = NULL, *tmp = NULL;
++      int i;  
 +
-+void vtoc_volume_label_set_volser (
-+      volume_label_t *vlabel,
-+      char *volser);
++      for (i=0; i<16; i++)
++      {
++              if (i<5) 
++                      ext = &f7->DS7EXTNT[i]; 
++              else 
++                      ext = &f7->DS7ADEXT[i-5];
 +
-+char *vtoc_volume_label_get_volser (
-+      volume_label_t *vlabel,
-+      char *volser);
++              if (((a < ext->a) && (b > ext->a) && (b < ext->b)) || 
++                  ((a > ext->a) && (a < ext->b) && (b > ext->b)))
++              {
++                      printf("BUG: overlapping free space extents " \
++                             "in FMT7 DSCB!\nexiting...\n");
++                      exit(1);
++              }
 +
-+void vtoc_volume_label_set_key (
-+        volume_label_t *vlabel,
-+        char *key);     
++              if ((ext->a + ext->b) == 0x00000000)
++              {
++                      ext->a = a;
++                      ext->b = b;
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "add new extent\n");
++                      break;
++              }
++      }
 +
-+void vtoc_volume_label_set_label (
-+      volume_label_t *vlabel,
-+      char *lbl);
++      if (tmp == NULL)
++      {
++              /* BUG: no free extent found */
++              printf("BUG: no free FMT7 DSCB extent found!\nexiting...\n");
++              exit(1);
++      }
 +
-+char *vtoc_volume_label_get_label (
-+      volume_label_t *vlabel,
-+      char *lbl);
++      for (i=0; i<16; i++)
++      {
++              if (i<5) 
++                      ext = &f7->DS7EXTNT[i]; 
++              else 
++                      ext = &f7->DS7ADEXT[i-5];
 +
-+void vtoc_read_label (
-+        int fd,
-+        unsigned long position,
-+        format1_label_t *f1,
-+        format4_label_t *f4,
-+        format5_label_t *f5,
-+        format7_label_t *f7);
++              if ((ext->a + ext->b) == 0x00000000)
++                      continue;
++
++              if ((ext->b + 1) == tmp->a)
++              {
++                      /* this extent precedes the new one */
++                      ext->b = tmp->b;
++                      bzero(tmp, sizeof(ds7ext_t));
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "merge with predecessor\n");
++                      i = -1;
++                      continue;
++              } 
 +
-+void vtoc_write_label (
-+        int fd,
-+        unsigned long position,
-+        format1_label_t *f1,
-+      format4_label_t *f4,
-+      format5_label_t *f5,
-+      format7_label_t *f7);
++              if (ext->a == (tmp->b + 1))
++              {
++                      /* this extent succeeds the new one */
++                      ext->a = tmp->a;
++                      bzero(tmp, sizeof(ds7ext_t));
++                      tmp = ext;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "merge with successor\n");
++                      i = -1;
++                      continue;
++              } 
++      }
++}
 +
 +
-+void vtoc_init_format1_label (
-+        char *volid,
-+        unsigned int blksize,
-+        extent_t *part_extent,
-+        format1_label_t *f1);
++/*
++ * remove a free space extent description from the VTOC FMT7 DSCB
++ */
++void 
++vtoc_update_format7_label_del (format7_label_t *f7, int verbose, 
++                             u_int32_t a, u_int32_t b) 
++{
++      PDEBUG
++      ds7ext_t *ext;
++      int i, counter=0;
++      
++      for (i=0; i<16; i++)
++      {
++              if (i<5) 
++                      ext = &f7->DS7EXTNT[i]; 
++              else 
++                      ext = &f7->DS7ADEXT[i-5];
 +
++              if ((a == ext->a) && (b == ext->b))
++              {
++                      /* fills up whole free space gap */
++                      bzero(ext, sizeof(ds7ext_t));
++                      if (verbose) 
++                              printf("FMT7 del extent: " \
++                                     "fills whole gap\n");
++                      counter++;
++                      break;
++              }
 +
-+void vtoc_init_format4_label (
-+        format4_label_t *f4lbl,
-+      unsigned int usable_partitions,
-+      unsigned int cylinders,
-+      unsigned int tracks,
-+      unsigned int blocks,
-+      unsigned int blksize,
-+      u_int16_t dev_type);
++              if ((a == ext->a) && (b < ext->b))
++              {
++                      /* left-bounded in free space gap */
++                      ext->a = b + 1;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "left-bounded\n");
++                      counter++;
++                      break;
++              }
 +
-+void vtoc_update_format4_label (
-+      format4_label_t *f4,
-+      cchhb_t *highest_f1,
-+      u_int16_t unused_update);
++              if ((a > ext->a) && (b == ext->b))
++              {
++                      /* right-bounded in free space gap */
++                      ext->b = a - 1;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "right-bounded\n");
++                      counter++;
++                      break;
++              }
 +
++              if ((a > ext->a) && (b < ext->b))
++              {
++                      /* partition devides free space into 2 pieces */
++                      vtoc_update_format7_label_add(f7, verbose, 
++                                                    b+1, ext->b);
++                      ext->b = a - 1;
++                      if (verbose) 
++                              printf("FMT7 add extent: " \
++                                     "2 pieces\n");
++                      counter++;
++                      break;
++              }
 +
-+void vtoc_init_format5_label (
-+      format5_label_t *f5);
++              if (((a < ext->a) && (b > ext->a)) || ((a < ext->b) && (b > ext->b)))
++              {
++                      printf ("BUG: specified free space extent for deleting "
++                              "doesn't match free space currently shown in "
++                              "FMT7 DSCB!\nexiting...\n");
++                      printf ("%d %d %d %d\n", a, b, ext->a, ext->b);
++                      exit(1);
++              }
++      }
 +
-+void vtoc_update_format5_label_add (
-+      format5_label_t *f5,
-+      int verbose,
-+      int cyl,
-+      int trk,
-+      u_int16_t a, 
-+      u_int16_t b, 
-+      u_int8_t c);
-+ 
-+void vtoc_update_format5_label_del (
-+      format5_label_t *f5,
-+      int verbose,
-+      int cyl,
-+      int trk,
-+      u_int16_t a, 
-+      u_int16_t b, 
-+      u_int8_t c);
++      if (counter > 0) return;
 +
++      printf("BUG: specified free space extent for " \
++             "deleting not found in FMT7 DSCB!\n" \
++             "exiting...\n");
++      exit(1);
++}
 +
-+void vtoc_init_format7_label (
-+      format7_label_t *f7);
 +
-+void vtoc_update_format7_label_add (
-+      format7_label_t *f7,
-+      int verbose,
-+      u_int32_t a, 
-+      u_int32_t b);
++/*
++ *
++ */
++void
++vtoc_set_freespace(format4_label_t *f4,
++                 format5_label_t *f5,
++                 format7_label_t *f7,
++                 char ch,
++                 int verbose,
++                 u_int32_t start,
++                 u_int32_t stop,
++                 int cyl,
++                 int trk)
++{
++      PDEBUG
++      if ((cyl * trk) > BIG_DISK_SIZE)
++      {
++              if (ch == '+')
++              {
++                      vtoc_update_format7_label_add(f7, verbose, 
++                                                    start, stop);
++              }
++              else if (ch == '-')
++              {
++                      vtoc_update_format7_label_del(f7, verbose, 
++                                                    start, stop);
++              }
++              else
++              {
++                      printf("BUG: syntax error in " \
++                             "vtoc_set_freespace call\n");
++              }
 +
-+void vtoc_update_format7_label_del (
-+      format7_label_t *f7, 
-+      int verbose,
-+      u_int32_t a, 
-+      u_int32_t b);
++              vtoc_reorganize_FMT7_extents (f7);
 +
++              f4->DS4VTOCI = 0xa0;
++              f4->DS4EFLVL = 0x07;
++              vtoc_set_cchhb(&f4->DS4EFPTR, 0x0000, 0x0001, 0x03);
++      }
++      else
++      {
++              u_int16_t x,y;
++              u_int8_t z;
 +
-+void vtoc_set_freespace(
-+      format4_label_t *f4,
-+      format5_label_t *f5,
-+      format7_label_t *f7,
-+      char ch,
-+      int verbose,
-+      u_int32_t start,
-+      u_int32_t stop,
-+      int cyl,
-+      int trk);
++              x = (u_int16_t) start;
++              y = (u_int16_t) ((stop - start + 1) / trk);
++              z =  (u_int8_t) ((stop - start + 1) % trk);
 +
++              if (ch == '+')
++              {
++                      vtoc_update_format5_label_add(f5, verbose,
++                                                    cyl, trk,
++                                                    x, y, z);
++              }
++              else if (ch == '-')
++              {
++                      vtoc_update_format5_label_del(f5, verbose, 
++                                                    cyl, trk,
++                                                    x, y, z);
++              }
++              else
++              {
++                      printf("BUG: syntax error in " \
++                             "vtoc_set_freespace call\n");
++              }
++              vtoc_reorganize_FMT5_extents (f5);
++      }
++              
++}
+diff -urN parted-1.7.0.orig/libparted/libparted.c parted-1.7.0/libparted/libparted.c
+--- parted-1.7.0.orig/libparted/libparted.c    2006-05-15 05:19:52.000000000 -0400
++++ parted-1.7.0/libparted/libparted.c 2006-05-19 14:37:55.000000000 -0400
+@@ -89,12 +89,17 @@
+ extern void ped_disk_pc98_init ();
+ extern void ped_disk_sun_init ();
+ extern void ped_disk_amiga_init ();
++extern void ped_disk_dasd_init ();
+ static void
+ init_disk_types ()
+ {
+       ped_disk_loop_init ();  /* must be last in the probe list */
++#if defined(__s390__) || defined(__s390x__)
++      ped_disk_dasd_init();
++#endif
 +
-+#endif /* VTOC_H */
+       ped_disk_sun_init ();
+ #ifdef ENABLE_PC98
+       ped_disk_pc98_init ();
+@@ -145,10 +150,14 @@
+ extern void ped_disk_pc98_done ();
+ extern void ped_disk_sun_done ();
+ extern void ped_disk_amiga_done ();
++extern void ped_disk_dasd_done ();
+ static void
+ done_disk_types ()
+ {
++#if defined(__s390__) || (__s390x__)
++      ped_disk_dasd_done ();
++#endif
+       ped_disk_sun_done ();
+ #ifdef ENABLE_PC98
+       ped_disk_pc98_done ();
This page took 0.361152 seconds and 4 git commands to generate.