fis-gtm/sr_unix/mu_op_open.c

428 lines
11 KiB
C

/****************************************************************
* *
* Copyright 2001, 2010 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_fcntl.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include "gtm_unistd.h"
#include "gtm_stat.h"
#include "gtm_iconv.h"
#include <errno.h>
#include <sys/ioctl.h>
#include "io.h"
#include "iosp.h"
#include "io_params.h"
#include "cryptdef.h"
#include "iotimer.h"
#include "gt_timer.h"
#include "copy.h"
#include "iottdef.h"
#include "iomtdef.h"
#include "mupip_io_dev_dispatch.h"
#ifdef KEEP_zOS_EBCDIC
#include "iormdef.h"
#endif
#include "eintr_wrappers.h"
#include "mmemory.h"
#include "mu_op_open.h"
#include "trans_log_name.h"
#include "gtm_conv.h"
#include "gtm_utf8.h"
#include "gtmimagename.h"
#define LOGNAME_LEN 255
GBLREF dev_dispatch_struct io_dev_dispatch_mupip[];
GBLREF bool licensed;
GBLREF int4 lkid,lid;
LITREF mstr chset_names[];
LITREF unsigned char io_params_size[];
GBLDEF io_desc *active_device;
GBLREF mstr sys_input;
GBLREF mstr sys_output;
static bool mu_open_try(io_log_name *, io_log_name *, mval *, mval *);
/* The third parameter is dummy to keep the inteface same as op_open */
int mu_op_open(mval *v, mval *p, int t, mval *mspace)
{
char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */
io_log_name *naml; /* logical record for passed name */
io_log_name *tl; /* logical record for translated name */
int4 stat; /* status */
mstr tn; /* translated name */
error_def(LP_NOTACQ); /* bad license */
error_def(ERR_LOGTOOLONG);
MV_FORCE_STR(v);
MV_FORCE_STR(p);
if (mspace)
MV_FORCE_STR(mspace);
if (t < 0)
t = 0;
assert((unsigned char)*p->str.addr < n_iops);
naml = get_log_name(&v->str, INSERT);
if (naml->iod != 0)
tl = naml;
else
{
# ifdef NOLICENSE
licensed= TRUE ;
# else
CRYPT_CHKSYSTEM;
if (!licensed || LP_CONFIRM(lid,lkid)==LP_NOTACQ)
{
licensed= FALSE ;
}
# endif
switch(stat = TRANS_LOG_NAME(&v->str, &tn, &buf1[0], SIZEOF(buf1), dont_sendmsg_on_log2long))
{
case SS_NORMAL:
tl = get_log_name(&tn, INSERT);
break;
case SS_NOLOGNAM:
tl = naml;
break;
case SS_LOG2LONG:
rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, v->str.len, v->str.addr, SIZEOF(buf1) - 1);
break;
default:
rts_error(VARLSTCNT(1) stat);
}
}
stat = mu_open_try(naml, tl, p, mspace);
return (stat);
}
static bool mu_open_try(io_log_name *naml, io_log_name *tl, mval *pp, mval *mspace)
{
int4 status;
mstr tn; /* translated name */
mstr chset_mstr;
int oflag;
unsigned char ch;
int file_des;
struct stat outbuf;
char *buf, namebuf[LOGNAME_LEN + 1];
d_mt_struct *mt_ptr;
int umask_orig, umask_creat;
int char_or_block_special;
int fstat_res;
int save_errno;
int p_offset;
boolean_t ichset_specified, ochset_specified, filecreated = FALSE;
error_def(ERR_SYSCALL);
mt_ptr = NULL;
char_or_block_special = FALSE;
file_des = -2;
oflag = 0;
tn.len = tl->len;
if (tn.len > LOGNAME_LEN)
tn.len = LOGNAME_LEN;
tn.addr = tl->dollar_io;
memcpy(namebuf, tn.addr, tn.len);
namebuf[tn.len] = '\0';
buf = namebuf;
if (0 == naml->iod)
{
if (0 == tl->iod)
{
tl->iod = (io_desc *)malloc(SIZEOF(io_desc));
memset((char*)tl->iod, 0, SIZEOF(io_desc));
tl->iod->pair.in = tl->iod;
tl->iod->pair.out = tl->iod;
tl->iod->trans_name = tl;
tl->iod->type = n_io_dev_types;
p_offset = 0;
while(iop_eol != *(pp->str.addr + p_offset))
{
ch = *(pp->str.addr + p_offset++);
if (iop_sequential == ch)
tl->iod->type = rm;
if (IOP_VAR_SIZE == io_params_size[ch])
p_offset += *(pp->str.addr + p_offset) + 1;
else
p_offset += io_params_size[ch];
}
}
if ((n_io_dev_types == tl->iod->type) && mspace && mspace->str.len)
tl->iod->type = us;
if (n_io_dev_types == tl->iod->type)
{
if (0 == memvcmp(tn.addr, tn.len, sys_input.addr, sys_input.len))
{
file_des = 0;
FSTAT_FILE(file_des, &outbuf, fstat_res);
if (-1 == fstat_res)
{
save_errno = errno;
rts_error(VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fstat()"),
CALLFROM, save_errno);
}
} else
{
if (0 == memvcmp(tn.addr, tn.len, sys_output.addr, sys_output.len))
{
file_des = 1;
FSTAT_FILE(file_des, &outbuf, fstat_res);
if (-1 == fstat_res)
{
save_errno = errno;
rts_error(VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fstat()"),
CALLFROM, save_errno);
}
} else if (0 == memvcmp(tn.addr, tn.len, "/dev/null", 9))
tl->iod->type = nl;
else if ((-1 == Stat(buf, &outbuf)) && (n_io_dev_types == tl->iod->type))
{
if (ENOENT == errno)
{
tl->iod->type = rm;
filecreated = TRUE;
}
else
{
save_errno = errno;
rts_error(VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fstat()"),
CALLFROM, save_errno);
}
}
}
}
if (n_io_dev_types == tl->iod->type)
{
switch(outbuf.st_mode & S_IFMT)
{
case S_IFCHR:
case S_IFBLK:
char_or_block_special = TRUE;
break;
case S_IFIFO:
tl->iod->type = ff;
break;
case S_IFREG:
case S_IFDIR:
tl->iod->type = rm;
break;
case S_IFSOCK:
case 0:
tl->iod->type = ff;
break;
default:
break;
}
}
naml->iod = tl->iod;
}
active_device = naml->iod;
if ((-2 == file_des) && (dev_open != naml->iod->state) && (us != naml->iod->type) && (tcp != naml->iod->type))
{
oflag |= (O_RDWR | O_CREAT | O_NOCTTY);
p_offset = 0;
ichset_specified = ochset_specified = FALSE;
while(iop_eol != *(pp->str.addr + p_offset))
{
assert((params) *(pp->str.addr + p_offset) < (params)n_iops);
switch ((ch = *(pp->str.addr + p_offset++)))
{
case iop_append:
if (rm == naml->iod->type)
oflag |= O_APPEND;
break;
case iop_contiguous:
break;
case iop_newversion:
if ((dev_open != naml->iod->state) && (rm == naml->iod->type))
oflag |= O_TRUNC;
break;
case iop_readonly:
oflag &= ~(O_RDWR | O_CREAT | O_WRONLY);
oflag |= O_RDONLY;
break;
case iop_writeonly:
oflag &= ~(O_RDWR | O_RDONLY);
oflag |= O_WRONLY | O_CREAT;
break;
case iop_ipchset:
#ifdef KEEP_zOS_EBCDIC
if ( (iconv_t)0 != naml->iod->input_conv_cd )
{
ICONV_CLOSE_CD(naml->iod->input_conv_cd);
}
SET_CODE_SET(naml->iod->in_code_set,
(char *)(pp->str.addr + p_offset + 1));
if (DEFAULT_CODE_SET != naml->iod->in_code_set)
ICONV_OPEN_CD(naml->iod->input_conv_cd,
(char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
break;
#endif
if (gtm_utf8_mode)
{
chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
chset_mstr.len = *(pp->str.addr + p_offset);
SET_ENCODING(naml->iod->ichset, &chset_mstr);
ichset_specified = TRUE;
}
break;
case iop_opchset:
#ifdef KEEP_zOS_EBCDIC
if ( (iconv_t)0 != naml->iod->output_conv_cd)
{
ICONV_CLOSE_CD(naml->iod->output_conv_cd);
}
SET_CODE_SET(naml->iod->out_code_set,
(char *)(pp->str.addr + p_offset + 1));
if (DEFAULT_CODE_SET != naml->iod->out_code_set)
ICONV_OPEN_CD(naml->iod->output_conv_cd, INSIDE_CH_SET,
(char *)(pp->str.addr + p_offset + 1));
break;
#endif
if (gtm_utf8_mode)
{
chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
chset_mstr.len = *(pp->str.addr + p_offset);
SET_ENCODING(naml->iod->ochset, &chset_mstr);
ochset_specified = TRUE;
}
break;
case iop_m:
case iop_utf8:
case iop_utf16:
case iop_utf16be:
case iop_utf16le:
if (gtm_utf8_mode)
{
naml->iod->ichset = naml->iod->ochset =
(iop_m == ch) ? CHSET_M :
(iop_utf8 == ch) ? CHSET_UTF8 :
(iop_utf16 == ch) ? CHSET_UTF16 :
(iop_utf16be == ch) ? CHSET_UTF16BE : CHSET_UTF16LE;
ichset_specified = ochset_specified = TRUE;
}
break;
default:
break;
}
if (IOP_VAR_SIZE == io_params_size[ch])
p_offset += *(pp->str.addr + p_offset) + 1;
else
p_offset += io_params_size[ch];
}
if (!ichset_specified)
naml->iod->ichset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
if (!ochset_specified)
naml->iod->ochset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
if (IS_UTF_CHSET(naml->iod->ichset) && CHSET_UTF16 != naml->iod->ichset)
get_chset_desc(&chset_names[naml->iod->ichset]);
if (IS_UTF_CHSET(naml->iod->ochset) && CHSET_UTF16 != naml->iod->ochset)
get_chset_desc(&chset_names[naml->iod->ochset]);
/* RW permissions for owner and others as determined by umask. */
umask_orig = umask(000); /* determine umask (destructive) */
(void)umask(umask_orig); /* reset umask */
umask_creat = 0666 & ~umask_orig;
/*
* the check for EINTR below is valid and should not be converte d to an EINTR
* wrapper macro, due to the other errno values being checked.
*/
while ((-1 == (file_des = OPEN3(buf, oflag, umask_creat))))
{
if ( EINTR == errno
|| ETXTBSY == errno
|| ENFILE == errno
|| EBUSY == errno
|| ((mb == naml->iod->type) && (ENXIO == errno)))
continue;
else
break;
}
if (-1 == file_des)
return FALSE;
}
assert (tcp != naml->iod->type);
#ifdef KEEP_zOS_EBCDIC
SET_CODE_SET(naml->iod->in_code_set, OUTSIDE_CH_SET);
if (DEFAULT_CODE_SET != naml->iod->in_code_set)
ICONV_OPEN_CD(naml->iod->input_conv_cd, OUTSIDE_CH_SET, INSIDE_CH_SET);
SET_CODE_SET(naml->iod->out_code_set, OUTSIDE_CH_SET);
if (DEFAULT_CODE_SET != naml->iod->out_code_set)
ICONV_OPEN_CD(naml->iod->output_conv_cd, INSIDE_CH_SET, OUTSIDE_CH_SET);
#endif
/* smw 99/12/18 not possible to be -1 here */
if (-1 == file_des)
{
rts_error(VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("open()"),
CALLFROM, save_errno);
}
if (n_io_dev_types == naml->iod->type)
{
if (isatty(file_des))
naml->iod->type = tt;
else if (char_or_block_special && file_des > 2)
/* assume mag tape */
naml->iod->type = mt;
else
naml->iod->type = rm;
}
assert(naml->iod->type < n_io_dev_types);
naml->iod->disp_ptr = &io_dev_dispatch_mupip[naml->iod->type];
active_device = naml->iod;
if (dev_never_opened == naml->iod->state)
{
naml->iod->wrap = DEFAULT_IOD_WRAP;
naml->iod->width = DEFAULT_IOD_WIDTH;
naml->iod->length = DEFAULT_IOD_LENGTH;
naml->iod->write_filter = 0; /* MUPIP should not use FILTER */
}
if (dev_open != naml->iod->state)
{
naml->iod->dollar.x = 0;
naml->iod->dollar.y = 0;
naml->iod->dollar.za = 0;
naml->iod->dollar.zb[0] = 0;
}
naml->iod->newly_created = filecreated;
status = (naml->iod->disp_ptr->open)(naml, pp, file_des, mspace, NO_M_TIMEOUT);
if (TRUE == status)
naml->iod->state = dev_open;
else if (dev_open == naml->iod->state)
naml->iod->state = dev_closed;
if (1 == file_des)
naml->iod->dollar.zeof = TRUE;
active_device = 0;
naml->iod->newly_created = FALSE;
if (IS_MCODE_RUNNING)
return (status);
return TRUE;
}