/**************************************************************** * * * Copyright 2001, 2011 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 #include #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 "iormdef.h" #include "mupip_io_dev_dispatch.h" #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 GBLDEF io_desc *active_device; GBLREF bool licensed; GBLREF dev_dispatch_struct io_dev_dispatch_mupip[]; GBLREF int4 lkid,lid; GBLREF mstr sys_input, sys_output; error_def(LP_NOTACQ); /* bad license */ error_def(ERR_LOGTOOLONG); error_def(ERR_SYSCALL); LITREF mstr chset_names[]; LITREF unsigned char io_params_size[]; 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 */ int4 stat; /* status */ io_log_name *naml; /* logical record for passed name */ io_log_name *tl; /* logical record for translated name */ mstr tn; /* translated name */ MV_FORCE_STR(v); MV_FORCE_STR(p); if (mspace) MV_FORCE_STR(mspace); if (0 > t) t = 0; assert((unsigned char)*p->str.addr < n_iops); naml = get_log_name(&v->str, INSERT); if (0 != naml->iod) 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) { boolean_t ichset_specified, ochset_specified, filecreated = FALSE; char *buf, namebuf[LOGNAME_LEN + 1]; d_rm_struct *d_rm; int char_or_block_special, file_des, fstat_res, oflag, p_offset, save_errno, umask_creat, umask_orig; int4 recordsize, status; io_desc *iod; mstr chset_mstr; mstr tn; /* translated name */ struct stat outbuf; unsigned char ch; 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 = iod = (io_desc *)malloc(SIZEOF(io_desc)); memset((char*)tl->iod, 0, SIZEOF(io_desc)); iod->pair.in = iod; iod->pair.out = iod; iod->trans_name = 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) 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 == iod->type) && mspace && mspace->str.len) iod->type = us; if (n_io_dev_types == 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)) iod->type = nl; else if ((-1 == Stat(buf, &outbuf)) && (n_io_dev_types == iod->type)) { if (ENOENT == errno) { 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 == iod->type) { switch (outbuf.st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: char_or_block_special = TRUE; break; case S_IFIFO: iod->type = ff; break; case S_IFREG: case S_IFDIR: iod->type = rm; break; case S_IFSOCK: case 0: iod->type = ff; break; default: break; } } naml->iod = iod; } else iod = naml->iod; active_device = iod; if ((-2 == file_des) && (dev_open != iod->state) && (us != iod->type) && (tcp != 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 == iod->type) oflag |= O_APPEND; break; case iop_contiguous: break; case iop_newversion: if ((dev_open != iod->state) && (rm == 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 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(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(iod->ichset, &chset_mstr); ichset_specified = TRUE; } break; case iop_opchset: # ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != iod->output_conv_cd) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(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(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) { iod->ichset = 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; } p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } if (!ichset_specified) iod->ichset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M; if (!ochset_specified) iod->ochset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M; if (IS_UTF_CHSET(iod->ichset) && CHSET_UTF16 != iod->ichset) get_chset_desc(&chset_names[iod->ichset]); if (IS_UTF_CHSET(iod->ochset) && CHSET_UTF16 != iod->ochset) get_chset_desc(&chset_names[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 == iod->type) && (ENXIO == errno))) continue; else break; } if (-1 == file_des) return FALSE; } assert (tcp != iod->type); #ifdef KEEP_zOS_EBCDIC SET_CODE_SET(iod->in_code_set, OUTSIDE_CH_SET); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, OUTSIDE_CH_SET, INSIDE_CH_SET); SET_CODE_SET(iod->out_code_set, OUTSIDE_CH_SET); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(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 == iod->type) { if (isatty(file_des)) iod->type = tt; else if (char_or_block_special && (2 < file_des)) { /* assume mag tape */ iod->type = mt; assert(FALSE); }else iod->type = rm; } assert(iod->type < n_io_dev_types); iod->disp_ptr = &io_dev_dispatch_mupip[iod->type]; active_device = iod; if (dev_never_opened == iod->state) { iod->wrap = DEFAULT_IOD_WRAP; iod->width = DEFAULT_IOD_WIDTH; iod->length = DEFAULT_IOD_LENGTH; iod->write_filter = 0; /* MUPIP should not use FILTER */ } if (dev_open != iod->state) { iod->dollar.x = 0; iod->dollar.y = 0; iod->dollar.za = 0; iod->dollar.zb[0] = 0; } iod->newly_created = filecreated; status = (iod->disp_ptr->open)(naml, pp, file_des, mspace, NO_M_TIMEOUT); if (TRUE == status) { iod->state = dev_open; if (rm == iod->type) { d_rm = (d_rm_struct *)iod->dev_sp; if (!d_rm->def_recsize && d_rm->def_width) { iod->width = d_rm->recordsize; d_rm->def_width = FALSE; } } } else if (dev_open == iod->state) iod->state = dev_closed; if (1 == file_des) iod->dollar.zeof = TRUE; active_device = 0; iod->newly_created = FALSE; if (IS_MCODE_RUNNING) return (status); return TRUE; }