Files
s390-tools/libvtoc/vtoc.c
Jan Höppner c15f481181 libvtoc: Replace strncpy() with memcpy()
To assemble things like the volume id or fields of the format1 label
struct, strncpy() is used. Data copied here is later written to disk and
we don't want any terminating null byte ('\0') there. Therefore, we can
simply use memcpy() instead and get rid of the following GCC8 compile
warnings:

vtoc.c: In function ‘vtoc_init_format_1_8_label’:
vtoc.c:747:2: warning: ‘strncpy’ output truncated before terminating nul
copying 6 bytes from a s tring of the same length [-Wstringop-truncation]
  strncpy((char *) f1->DS1DSSN, "      ", 6);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vtoc.c:746:2: warning: ‘strncpy’ output may be truncated copying 44 bytes from
a string of length 79 [-Wstringop-truncation]
  strncpy(f1->DS1DSNAM, str, 44);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vtoc.c:761:2: warning: ‘strncpy’ output may be truncated copying 13 bytes from
a string of length 79 [-Wstringop-truncation]
  strncpy((char *)f1->DS1SYSCD, str, 13);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vtoc.c: In function ‘vtoc_volume_label_set_volser’:
vtoc.c:401:2: warning: ‘strncpy’ output may be truncated copying 6 bytes from a
string of length 6 [-Wstringop-truncation]
  strncpy(vlabel->volid, s, VOLSER_LENGTH);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2018-11-16 15:01:41 +01:00

1365 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 "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, u_int8_t typeind, u_int8_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, u_int32_t cc, u_int16_t hh)
{
addr->cc = (u_int16_t) cc;
addr->hh = cc >> 16;
addr->hh <<= 4;
addr->hh |= hh;
}
u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr)
{
u_int32_t cyl;
/*decode cylinder for large volumes */
cyl = addr->hh & 0xFFF0;
cyl <<= 12;
cyl |= addr->cc;
return cyl;
}
u_int16_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, u_int16_t tt, u_int8_t r)
{
addr->tt = tt;
addr->r = r;
}
/*
*
*/
void vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b)
{
addr->cc = (u_int16_t) cc;
addr->hh = cc >> 16;
addr->hh <<= 4;
addr->hh |= hh;
addr->b = b;
}
u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr)
{
u_int32_t cyl;
/* decode cylinder for large volumes */
cyl = addr->hh & 0xFFF0;
cyl <<= 12;
cyl |= addr->cc;
return cyl;
}
u_int16_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!
*/
u_int64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo)
{
return (u_int64_t) vtoc_get_cyl_from_cchhb(p) *
geo->heads * geo->sectors +
vtoc_get_head_from_cchhb(p) * geo->sectors +
p->b;
}
u_int64_t cchh2blk (cchh_t *p, struct hd_geometry *geo) {
return (u_int64_t) vtoc_get_cyl_from_cchh(p) *
geo->heads * geo->sectors +
vtoc_get_head_from_cchh(p) * geo->sectors;
}
u_int32_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, u_int8_t year, u_int16_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,
u_int16_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 -- */
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));
f4->DS4DCYL = real_cylinders;
bzero(f4->res4, sizeof(f4->res4));
f4->DS4DEVF2 = 0x40; /* allow format 8 and 9 labels */
bzero(&f4->res5, sizeof(f4->res5));
}
/*
* initializes a format5 label
*/
void
vtoc_init_format5_label (format5_label_t *f5)
{
int i;
bzero(f5, 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;
bzero(f7, 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);
bzero(f1->DS1DSNAM, 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,
(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);
memcpy((char *)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);
}
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,
u_int16_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,
u_int16_t a,
u_int16_t b,
u_int8_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;
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 trk,
u_int16_t a,
u_int16_t b,
u_int8_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 */
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;
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,
u_int32_t a, u_int32_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;
bzero(tmp, 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;
bzero(tmp, 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,
u_int32_t a, u_int32_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 */
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;
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 devides 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,
u_int32_t start, u_int32_t stop, u_int32_t cyl, u_int32_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 {
u_int16_t x,y;
u_int8_t z;
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, 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);
}
}