Files
s390-tools/libvtoc/vtoc.c
Jan Polensky 06df08ae49 libvtoc: Convert comments from ISO-8859-1 to UTF-8
Convert comment encoding from ISO-8859-1 to UTF-8 to avoid encoding
mismatches and simplify future maintenance.

Align the libvtoc comments with the change introduced in the kernel
by commit 8f2bc80c6ef8 ("s390: ebcdic: convert comments to UTF-8").

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-02-12 13:11:44 +01:00

1367 lines
31 KiB
C

/*
* Copyright IBM Corp. 2001, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*
*/
#include <stdint.h>
#include "lib/vtoc.h"
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];
/*
*
*/
static void vtoc_error(enum failure why, char *s1, char *s2)
{
switch (why) {
case unable_to_open:
fprintf(stderr, "\n%s opening device '%s' failed.\n%s\n",
VTOC_ERROR, s1, s2);
break;
case unable_to_seek:
fprintf(stderr, "\n%s seeking device '%s' failed.\n%s\n",
VTOC_ERROR, s1, s2);
break;
case unable_to_write:
fprintf(stderr, "\n%s writing to device '%s' failed,\n%s\n",
VTOC_ERROR, s1, s2);
break;
case unable_to_read:
fprintf(stderr, "\n%s reading from device '%s' failed.\n%s\n",
VTOC_ERROR, s1, s2);
break;
default: fprintf(stderr, "\nFatal error\n");
}
exit(1);
}
/*
*
*/
char * vtoc_ebcdic_enc (char *source, char *target, int l)
{
int i;
for (i = 0; i < l; i++)
target[i]=ASCtoEBC[(unsigned char)(source[i])];
return target;
}
/*
*
*/
char * vtoc_ebcdic_dec (char *source, char *target, int l)
{
int i;
for (i = 0; i < l; i++)
target[i]=EBCtoASC[(unsigned char)(source[i])];
return target;
}
/*
*
*/
void vtoc_set_extent (extent_t *ext, uint8_t typeind, uint8_t seqno,
cchh_t *lower, cchh_t *upper)
{
ext->typeind = typeind;
ext->seqno = seqno;
memcpy(&ext->llimit,lower,sizeof(cchh_t));
memcpy(&ext->ulimit,upper,sizeof(cchh_t));
}
/*
*
*/
void vtoc_set_cchh (cchh_t *addr, uint32_t cc, uint16_t hh)
{
addr->cc = (uint16_t) cc;
addr->hh = cc >> 16;
addr->hh <<= 4;
addr->hh |= hh;
}
uint32_t vtoc_get_cyl_from_cchh(cchh_t *addr)
{
uint32_t cyl;
/*decode cylinder for large volumes */
cyl = addr->hh & 0xFFF0;
cyl <<= 12;
cyl |= addr->cc;
return cyl;
}
uint16_t vtoc_get_head_from_cchh(cchh_t *addr)
{
/* decode heads for large volumes */
return addr->hh & 0x000F;
}
/*
*
*/
static void vtoc_set_ttr (ttr_t *addr, uint16_t tt, uint8_t r)
{
addr->tt = tt;
addr->r = r;
}
/*
*
*/
void vtoc_set_cchhb (cchhb_t *addr, uint32_t cc, uint16_t hh, uint8_t b)
{
addr->cc = (uint16_t) cc;
addr->hh = cc >> 16;
addr->hh <<= 4;
addr->hh |= hh;
addr->b = b;
}
uint32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr)
{
uint32_t cyl;
/* decode cylinder for large volumes */
cyl = addr->hh & 0xFFF0;
cyl <<= 12;
cyl |= addr->cc;
return cyl;
}
uint16_t vtoc_get_head_from_cchhb(cchhb_t *addr)
{
/* decode heads for large volumes */
return addr->hh & 0x000F;
}
/*
* some functions to convert cyl-cyl-head-head addresses to
* block or track numbers
* Note: Record zero is special, so first block on a track is
* in record 1!
*/
uint64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo)
{
return (uint64_t) vtoc_get_cyl_from_cchhb(p) *
geo->heads * geo->sectors +
vtoc_get_head_from_cchhb(p) * geo->sectors +
p->b;
}
uint64_t cchh2blk (cchh_t *p, struct hd_geometry *geo) {
return (uint64_t) vtoc_get_cyl_from_cchh(p) *
geo->heads * geo->sectors +
vtoc_get_head_from_cchh(p) * geo->sectors;
}
uint32_t cchh2trk (cchh_t *p, struct hd_geometry *geo) {
return vtoc_get_cyl_from_cchh(p) * geo->heads +
vtoc_get_head_from_cchh(p);
}
/*
*
*/
void vtoc_set_date (labeldate_t * d, uint8_t year, uint16_t day)
{
d->year = year;
d->day = day;
}
/*
* initializes the volume label with EBCDIC blanks
*/
void vtoc_volume_label_init (volume_label_t *vlabel)
{
sprintf(buffer, "%84s", " ");
vtoc_ebcdic_enc(buffer, buffer, 84);
memcpy(vlabel, buffer, 84);
}
/*
* reads the volume label from dasd
*/
int vtoc_read_volume_label (char *device, unsigned long vlabel_start,
volume_label_t *vlabel)
{
int f, rc;
if ((f = open(device, O_RDONLY)) < 0) {
vtoc_error(unable_to_open, device,
"Could not read volume label.");
}
if (lseek(f, vlabel_start, SEEK_SET) < 0) {
close(f);
vtoc_error(unable_to_seek, device,
"Could not read volume label.");
}
rc = read(f, vlabel, sizeof(volume_label_t));
if (rc != sizeof(volume_label_t)) {
close(f);
vtoc_error(unable_to_read, device,
"Could not read volume label.");
}
close(f);
return 0;
}
/*
* writes the volume label to dasd
*/
int vtoc_write_volume_label (char *device, unsigned long vlabel_start,
volume_label_t *vlabel)
{
int rc, f;
if ((f = open(device, O_WRONLY)) < 0) {
vtoc_error(unable_to_open, device,
"Could not write volume label.");
}
if (lseek(f, vlabel_start, SEEK_SET) < 0) {
close(f);
vtoc_error(unable_to_seek, device,
"Could not write volume label.");
}
rc = write(f, vlabel, sizeof(volume_label_t));
if (rc != sizeof(volume_label_t))
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write volume label.");
}
close(f);
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
*/
void vtoc_volume_label_set_volser (volume_label_t *vlabel, char *volser)
{
int j, i = strlen(volser);
char s[VOLSER_LENGTH + 1];
strcpy(s, " ");
vtoc_ebcdic_enc(s, s, VOLSER_LENGTH);
memcpy(vlabel->volid, s, VOLSER_LENGTH);
if (i > VOLSER_LENGTH) i = VOLSER_LENGTH;
strncpy(s, volser, i);
for (j=0; j<i; j++) {
s[j] = toupper(s[j]);
}
s[VOLSER_LENGTH] = 0x00;
vtoc_ebcdic_enc(s, s, i);
strncpy(vlabel->volid, s, i);
return;
}
/*
* returns the volume serial number right after it is translated
* to ASCII
*/
char * vtoc_volume_label_get_volser (volume_label_t *vlabel, char *volser)
{
vtoc_ebcdic_dec(vlabel->volid, volser, VOLSER_LENGTH);
volser[VOLSER_LENGTH] = '\0';
return volser;
}
/*
* 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)
{
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
*/
void vtoc_volume_label_set_label (volume_label_t *vlabel, char *lbl)
{
char s[4];
vtoc_ebcdic_enc(lbl, s, 4);
strncpy(vlabel->vollbl, s, 4);
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)
{
vtoc_ebcdic_dec(vlabel->vollbl, lbl, 4);
lbl[4] = '\0';
return lbl;
}
/*
* reads either a format4 label or a format1 label
* from the specified position
*/
void vtoc_read_label (char *device, unsigned long position,
format1_label_t *f1, format4_label_t *f4,
format5_label_t *f5, format7_label_t *f7)
{
int f,t;
if ((f = open(device, O_RDONLY)) < 0)
vtoc_error(unable_to_open, device,
"Could not read VTOC labels.");
if (lseek(f, position, SEEK_SET) < 0) {
close(f);
vtoc_error(unable_to_seek, device,
"Could not read VTOC labels.");
}
if (f1 != NULL) {
t = sizeof(format1_label_t);
if (read(f, f1, t) != t) {
close(f);
vtoc_error(unable_to_read, device,
"Could not read VTOC FMT1 DSCB.");
}
}
if (f4 != NULL) {
t = sizeof(format4_label_t);
if (read(f, f4, t) != t) {
close(f);
vtoc_error(unable_to_read, device,
"Could not read VTOC FMT4 DSCB.");
}
}
if (f5 != NULL) {
t = sizeof(format5_label_t);
if (read(f, f5, t) != t) {
close(f);
vtoc_error(unable_to_read, device,
"Could not read VTOC FMT5 DSCB.");
}
}
if (f7 != NULL) {
t = sizeof(format7_label_t);
if (read(f, f7, t) != t) {
close(f);
vtoc_error(unable_to_read, device,
"Could not read VTOC FMT7 DSCB.");
}
}
close(f);
}
/*
* writes either a FMT1, FMT4 or FMT5 label
* to the specified position
*/
void
vtoc_write_label (char *device,
unsigned long position,
format1_label_t *f1,
format4_label_t *f4,
format5_label_t *f5,
format7_label_t *f7,
format9_label_t *f9)
{
int f,t;
if ((f = open(device, O_WRONLY)) == -1)
{
vtoc_error(unable_to_open, device,
"Could not write VTOC labels.");
}
if (lseek(f, position, SEEK_SET) == -1)
{
close(f);
vtoc_error(unable_to_seek, device,
"Could not write VTOC labels.");
}
if (f1 != NULL)
{
t = sizeof(format1_label_t);
if (write(f, f1, t) != t)
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write VTOC FMT1 DSCB.");
}
}
if (f4 != NULL)
{
t = sizeof(format4_label_t);
if (write(f, f4, t) != t)
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write VTOC FMT4 DSCB.");
}
}
if (f5 != NULL)
{
t = sizeof(format5_label_t);
if (write(f, f5, t) != t)
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write VTOC FMT5 DSCB.");
}
}
if (f7 != NULL)
{
t = sizeof(format7_label_t);
if (write(f, f7, t) != t)
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write VTOC FMT7 DSCB.");
}
}
if (f9 != NULL)
{
t = sizeof(format9_label_t);
if (write(f, f9, t) != t)
{
close(f);
vtoc_error(unable_to_write, device,
"Could not write VTOC FMT9 DSCB.");
}
}
close(f);
}
/*
* initializes a format4 label
*/
void
vtoc_init_format4_label (
format4_label_t *f4,
unsigned int compat_cylinders,
unsigned int real_cylinders,
unsigned int tracks,
unsigned int blocks,
unsigned int blksize,
uint16_t dev_type)
{
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 = compat_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 -- */
memset(f4->DS4AMTIM, 0, sizeof(f4->DS4AMTIM));
memset(f4->DS4AMCAT, 0, sizeof(f4->DS4AMCAT));
memset(f4->DS4R2TIM, 0, sizeof(f4->DS4R2TIM));
memset(f4->res1, 0, sizeof(f4->res1));
memset(f4->DS4F6PTR, 0, sizeof(f4->DS4F6PTR));
/* -- begin f4lbl->DS4VTOCE -- */
vtoc_set_extent(&f4->DS4VTOCE, 0x01, 0x00, &lower, &upper);
/* -- end f4lbl->DS4VTOCE -- */
memset(f4->res2, 0, sizeof(f4->res2));
f4->DS4EFLVL = 0x00;
memset(&f4->DS4EFPTR, 0, sizeof(f4->DS4EFPTR));
memset(&f4->res3, 0, sizeof(f4->res3));
f4->DS4DCYL = real_cylinders;
memset(f4->res4, 0, sizeof(f4->res4));
f4->DS4DEVF2 = 0x40; /* allow format 8 and 9 labels */
memset(&f4->res5, 0, sizeof(f4->res5));
}
/*
* initializes a format5 label
*/
void
vtoc_init_format5_label (format5_label_t *f5)
{
int i;
memset(f5, 0, sizeof(format5_label_t));
for (i=0; i<4; i++) f5->DS5KEYID[i] = 0x05;
f5->DS5FMTID = 0xf5;
}
/*
* initializes a format7 label
*/
void
vtoc_init_format7_label (format7_label_t *f7)
{
int i;
memset(f7, 0, sizeof(format7_label_t));
for (i=0; i<4; i++) f7->DS7KEYID[i] = 0x07;
f7->DS7FMTID = 0xf7;
}
/*
* helper function that initializes a most parts of a
* format1 or format 8 label, all but the field DS1FMTID
*/
static void vtoc_init_format_1_8_label (
unsigned int blksize,
extent_t *part_extent,
format1_label_t *f1)
{
struct tm * creatime;
time_t t;
char str[80];
/* get actual date */
t = time(NULL);
creatime = gmtime(&t);
memset(f1->DS1DSNAM, 0, sizeof(f1->DS1DSNAM));
sprintf(str, "PART .NEW ");
vtoc_ebcdic_enc(str, str, 44);
memcpy(f1->DS1DSNAM, str, 44);
memcpy((char *) f1->DS1DSSN, " ", 6);
f1->DS1VOLSQ = 0x0001;
vtoc_set_date(&f1->DS1CREDT,
(uint8_t) creatime->tm_year,
(uint16_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);
memcpy((char *)f1->DS1SYSCD, str, 13);
vtoc_set_date(&f1->DS1REFD,
(uint8_t) creatime->tm_year,
(uint16_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;
memset(&f1->DS1SCAL3, 0, sizeof(f1->DS1SCAL3));
vtoc_set_ttr(&f1->DS1LSTAR,
0x0000,
0x00);
f1->DS1TRBAL = 0x00;
memset(&f1->res1, 0, sizeof(f1->res1));
memcpy(&f1->DS1EXT1,
part_extent,
sizeof(extent_t));
memset(&f1->DS1EXT2, 0, sizeof(extent_t));
memset(&f1->DS1EXT3, 0, sizeof(extent_t));
vtoc_set_cchhb(&f1->DS1PTRDS,
0x0000, 0x0000, 0x00);
}
void vtoc_init_format1_label (
unsigned int blksize,
extent_t *part_extent,
format1_label_t *f1)
{
vtoc_init_format_1_8_label(blksize, part_extent, f1);
f1->DS1FMTID = 0xf1;
}
void vtoc_init_format8_label (
unsigned int blksize,
extent_t *part_extent,
format1_label_t *f8)
{
vtoc_init_format_1_8_label(blksize, part_extent, f8);
f8->DS1FMTID = 0xf8;
}
void vtoc_update_format8_label (
cchhb_t *associated_f9,
format1_label_t *f8)
{
memcpy(&f8->DS1PTRDS, associated_f9, sizeof(*associated_f9));
}
void vtoc_init_format9_label (
format9_label_t *f9)
{
f9->DS9KEYID = 0x09;
f9->DS9SUBTY = 0x01;
f9->DS9NUMF9 = 1;
f9->DS9FMTID = 0xf9;
}
/*
* do some updates to the VTOC format4 label
*/
void
vtoc_update_format4_label (
format4_label_t *f4,
cchhb_t *highest_f1,
uint16_t unused_update)
{
/* update highest address of a format 1 label */
memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
/* update unused DSCB count */
f4->DS4DSREC = unused_update;
}
/*
* reorganizes all extents within a FMT5 label
*/
static void
vtoc_reorganize_FMT5_extents (format5_label_t *f5)
{
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];
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;
}
}
}
}
/*
* add a free space extent description to the VTOC FMT5 DSCB
*/
void
vtoc_update_format5_label_add (format5_label_t *f5,
int verbose,
int trk,
uint16_t a,
uint16_t b,
uint8_t c)
{
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);
}
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);
}
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;
memset(tmp, 0, 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;
memset(tmp, 0, 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 trk,
uint16_t a,
uint16_t b,
uint8_t c)
{
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 */
memset(ext, 0, 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 divides free space into 2 pieces */
uint16_t x = a + b*trk + c;
uint16_t w,y;
uint8_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,
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);
}
/*
* reorganizes all extents within a FMT7 label
*/
static void
vtoc_reorganize_FMT7_extents (format7_label_t *f7)
{
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];
for (j=i; j<16; j++)
{
if (j<5)
ext = &f7->DS7EXTNT[j];
else
ext = &f7->DS7ADEXT[j-5];
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;
}
}
}
}
/*
* add a free space extent description to the VTOC FMT7 DSCB
*/
void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
uint32_t a, uint32_t b)
{
ds7ext_t *ext = NULL, *tmp = NULL;
int i;
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->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 ((ext->a + ext->b) == 0x00000000) {
ext->a = a;
ext->b = b;
tmp = ext;
if (verbose)
printf("FMT7 add extent: add new extent\n");
break;
}
}
if (tmp == NULL) {
printf("BUG: no free FMT7 DSCB extent found!\nexiting...\n");
exit(1);
}
for (i=0; i<16; i++) {
if (i<5)
ext = &f7->DS7EXTNT[i];
else
ext = &f7->DS7ADEXT[i-5];
if ((ext->a + ext->b) == 0x00000000)
continue;
if ((ext->b) == tmp->a) {
/* this extent precedes the new one */
ext->b = tmp->b;
memset(tmp, 0, sizeof(ds7ext_t));
tmp = ext;
if (verbose)
printf("FMT7 add extent: " \
"merge with predecessor\n");
i = -1;
continue;
}
if (ext->a == (tmp->b))
{
/* this extent succeeds the new one */
ext->a = tmp->a;
memset(tmp, 0, sizeof(ds7ext_t));
tmp = ext;
if (verbose)
printf("FMT7 add extent: " \
"merge with successor\n");
i = -1;
continue;
}
}
}
/*
* remove a free space extent description from the VTOC FMT7 DSCB
*/
void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
uint32_t a, uint32_t b)
{
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 */
memset(ext, 0, 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;
if (verbose)
printf("FMT7 add extent: left-bounded\n");
counter++;
break;
}
if ((a > ext->a) && (b == ext->b)) {
/* right-bounded in free space gap */
ext->b = a;
if (verbose)
printf("FMT7 add extent: right-bounded\n");
counter++;
break;
}
if ((a > ext->a) && (b < ext->b)) {
/* partition divides free space into 2 pieces */
vtoc_update_format7_label_add(f7, verbose,
b, ext->b);
ext->b = a;
if (verbose)
printf("FMT7 add extent: 2 pieces\n");
counter++;
break;
}
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");
exit(1);
}
}
if (counter > 0) return;
printf("BUG: specified free space extent for deleting not found "
"in FMT7 DSCB!\nexiting...\n");
exit(1);
}
/*
*
*/
void vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
format7_label_t *f7, char ch, int verbose,
uint32_t start, uint32_t stop, uint32_t cyl, uint32_t trk)
{
if ((cyl * trk) > BIG_DISK_SIZE) {
if (ch == '+') {
vtoc_update_format7_label_add(f7, verbose, start,
/* ds7ext RTA + 1 */
stop + 1);
}
else if (ch == '-') {
vtoc_update_format7_label_del(f7, verbose, start,
/* ds7ext RTA + 1 */
stop + 1);
}
else {
printf("BUG: syntax error in vtoc_set_freespace.\n");
}
vtoc_reorganize_FMT7_extents (f7);
f4->DS4VTOCI = 0xa0;
f4->DS4EFLVL = 0x07;
vtoc_set_cchhb(&f4->DS4EFPTR, 0x0000, 0x0001, 0x03);
} else {
uint16_t x,y;
uint8_t z;
x = (uint16_t) start;
y = (uint16_t) ((stop - start + 1) / trk);
z = (uint8_t) ((stop - start + 1) % trk);
if (ch == '+') {
vtoc_update_format5_label_add(f5, verbose, trk,
x, y, z);
}
else if (ch == '-') {
vtoc_update_format5_label_del(f5, verbose, trk,
x, y, z);
}
else {
printf("BUG: syntax error in vtoc_set_freespace.\n");
}
vtoc_reorganize_FMT5_extents (f5);
}
}