---- 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, §or_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 ();