void geteditor(void) { char *edt, **pedt; short len; int stat_res, iter; struct stat edt_stat; char *editor_list[] = { "/usr/bin/vi", "/usr/ucb/vi", "/bin/vi", /* Linux */ 0 /* this array should be terminated by a 0 */ }; edt = GETENV("EDITOR"); pedt = &editor_list[0]; do { STAT_FILE(edt, &edt_stat, stat_res); if (!stat_res) break; edt = *pedt++; } while (edt); if (edt) { len = strlen(edt) + 1; /* for zero */ editor.len = len - 1; /* but not for mstr */ editor.addr = (char*) malloc(len); /* must be zero term */ memcpy(editor.addr, edt, len); } else editor.len = 0; }
/* Return the group id of the distribution based on libgtmshr.xx[x]. If there is some * problem accessing that file then return INVALID_GID which signals no change to group. Otherwise, * the pointer to the stat buffer will contain the result of the call to STAT_FILE. */ gid_t gtm_get_group_id(struct stat *stat_buff) { char *env_var; int ret_stat; char temp[PATH_MAX + SIZEOF("libgtmshr.dll")]; static boolean_t first_time = TRUE; static struct stat st_buff; if (!first_time) { *stat_buff = st_buff; return st_buff.st_gid; } env_var = GETENV("gtm_dist"); if (NULL != env_var) { /* build a path to libgtmshr.so or .sl on hpux or .dll on zos */ SNPRINTF(temp, SIZEOF(temp), LIBGTMSHR, env_var); STAT_FILE(temp, stat_buff, ret_stat); if (0 == ret_stat) { first_time = FALSE; st_buff = *stat_buff; return(stat_buff->st_gid); } } /* return INVALID_GID if $gtm_dist found or if STAT_FILE returned a -1 */ return (INVALID_GID); }
/* This function will process I/O if -OUTPUT suboption is present. This will create the file and duplicate it as stderr. So anything written to stderr will be written to this file. */ bool open_fileio(int *save_stderr) { char ofnamebuf[1024]; mstr ofname; int status=FALSE, fd; unsigned short len; char *errmsg; #ifdef __MVS__ int realfiletag, fstatus; struct stat info; /* Need the ERR_BADTAG and ERR_TEXT error_defs for the TAG_POLICY macro warning */ error_def(ERR_TEXT); error_def(ERR_BADTAG); #endif *save_stderr = SYS_STDERR; ofname.addr=ofnamebuf; ofname.len=SIZEOF(ofnamebuf); if (cli_present("OUTPUT") == CLI_PRESENT) { len = ofname.len; if (cli_get_str("OUTPUT", ofname.addr, &len)) { int dup2_res; ZOS_ONLY(STAT_FILE(ofname.addr, &info, fstatus);)
/* Return the group id of the distribution based on libgtmshr.xx[x]. If there is some * problem accessing that file then return INVALID_GID which signals no change to group. Otherwise, * the pointer to the stat buffer will contain the result of the call to STAT_FILE. */ gid_t gtm_get_group_id(struct stat *stat_buff) { int ret_stat; char temp[GTM_PATH_MAX]; static boolean_t first_time = TRUE; static struct stat st_buff; if (!first_time) { *stat_buff = st_buff; return st_buff.st_gid; } if (gtm_dist_ok_to_use) { /* build a path to libgtmshr.so or .sl on hpux or .dll on zos */ SNPRINTF(temp, SIZEOF(temp), LIBGTMSHR, gtm_dist); STAT_FILE(temp, stat_buff, ret_stat); if (0 == ret_stat) { first_time = FALSE; st_buff = *stat_buff; return(stat_buff->st_gid); } } /* return INVALID_GID if STAT_FILE returned a -1 or gtm_dist has not been validated */ return (INVALID_GID); }
/* This appends timestamp from file (fn) last modified status time. Result is returned in same string fn. * Return SS_NORMAL for success */ uint4 append_time_stamp(char *fn, int fn_len, int *app_len, uint4 *ustatus) { struct stat stat_buf; struct tm *tm_struct; int status; size_t tt; *ustatus = SS_NORMAL; STAT_FILE(fn, &stat_buf, status); if (-1 == status) /* if file fn does not exist */ return errno; assert(0 < MAX_FN_LEN - fn_len - 1); tm_struct = localtime(&(stat_buf.st_ctime)); STRFTIME(&fn[fn_len], MAX_FN_LEN - fn_len - 1, TIME_EXT_FMT, tm_struct, tt); *app_len = (int)tt; return SS_NORMAL; }
/*! @brief Test a file for various attributes, via \c stat(2). @ingroup system_io @param file Pathname to test. If \c NULL, the results of the most recent \c stat(2) are used. @param test Type of test. @return Yes or no. */ int v_test(char *file, enum v_testtype test) { int retval = 0; /* Stat the file */ STAT_FILE(file); if (!statok) return 0; /* Do the test */ switch (test) { case V_TEST_EXISTS: retval = 1; break; case V_TEST_DIR: retval = S_ISDIR(statbuf.st_mode); break; case V_TEST_CHR: retval = S_ISCHR(statbuf.st_mode); break; case V_TEST_BLK: retval = S_ISBLK(statbuf.st_mode); break; case V_TEST_REG: retval = S_ISREG(statbuf.st_mode); break; case V_TEST_FIFO: retval = S_ISFIFO(statbuf.st_mode); break; case V_TEST_LNK: retval = S_ISLNK(statbuf.st_mode); break; case V_TEST_SOCK: retval = S_ISSOCK(statbuf.st_mode); break; default: v_exception("v_test(): invalid test type"); break; } return retval; }
/*! @brief Return list of \c stat(2) information on a file. @ingroup system_io @param file Filename to stat. If \c NULL, stat information from the most recent \c stat(2) call is used. @return List of stat info (pointer to internal buffer). @retval NULL if the file doesn't exist. The list contains the following entries: -# device number of filesystem -# inode number -# file mode (type and permissions) -# number of (hard) links to the file -# numeric user ID of file's owner -# numer group ID of file's owner -# the device identifier (special files only) -# total size of file, in bytes -# last access time since the epoch -# last modify time since the epoch -# inode change time (NOT creation time!) since the epoch -# preferred blocksize for file system I/O -# actual number of blocks allocated */ vlist * v_stat(char *file) { static vlist *l = NULL; /* Get stat info */ STAT_FILE(file); if (!statok) return NULL; /* Initialise */ vl_init(l); /* Store info */ vl_istore(l, 0, (int) statbuf.st_dev); vl_istore(l, 1, statbuf.st_ino); vl_istore(l, 2, statbuf.st_mode); vl_istore(l, 3, statbuf.st_nlink); vl_istore(l, 4, statbuf.st_uid); vl_istore(l, 5, statbuf.st_gid); #ifdef HAVE_STRUCT_STAT_ST_RDEV vl_istore(l, 6, (int) statbuf.st_rdev); #endif vl_istore(l, 7, statbuf.st_size); vl_istore(l, 8, statbuf.st_atime); vl_istore(l, 9, statbuf.st_mtime); vl_istore(l, 10, statbuf.st_ctime); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE vl_istore(l, 11, statbuf.st_blksize); #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS vl_istore(l, 12, statbuf.st_blocks); #endif return l; }
void dir_srch (parse_blk *pfil) { struct stat statbuf; int stat_res; lv_val *dir1, *dir2, *tmp; mstr tn; short p2_len; char filb[MAX_FBUFF + 1], patb[sizeof(ptstr)], *c, *lastd, *top, *p2, *c1, ch; mval pat_mval, sub, compare; bool wildname, seen_wd; struct dirent *dent; DIR *dp; plength *plen; int closedir_res; op_kill(zsrch_dir1); op_kill(zsrch_dir2); if (!pfil->b_name) return; /* nothing to search for */ ESTABLISH(dir_ch); pat_mval.mvtype = MV_STR; pat_mval.str.addr = patb; /* patb should be sizeof(ptstr.buff) but instead is sizeof(ptstr) since the C compiler * complains about the former and the latter is just 4 bytes more */ pat_mval.str.len = 0; sub.mvtype = MV_STR; sub.str.len = 0; compare.mvtype = MV_STR; compare.str.len = 0; wildname = (pfil->fnb & F_WILD_NAME) != 0; dir1 = zsrch_dir1; dir2 = zsrch_dir2; if (pfil->fnb & F_WILD_DIR) { seen_wd = FALSE; for (c = pfil->l_dir, lastd = c, top = c + pfil->b_dir; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } assert(c <= top); sub.str.addr = pfil->l_dir; sub.str.len = lastd - sub.str.addr; tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; for(;;) { tn.addr = lastd; /* wildcard segment */ tn.len = c - lastd - 1; lastd = c; genpat(&tn, &pat_mval); seen_wd = FALSE; p2 = c - 1; for (; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } p2_len = lastd - p2; /* length of non-wild segment after wild section */ for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while(READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = strlen(&dent->d_name[0]); assert(compare.str.len); if ( dent->d_name[0] == '.' && (compare.str.len == 1 || (compare.str.len == 2 && dent->d_name[1] == '.')) ) { continue; /* don't want to read . and .. */ } if (compare.str.len + sub.str.len + p2_len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ if (stringpool.free + compare.str.len + sub.str.len + p2_len + 1 > stringpool.top) stp_gcol(compare.str.len + sub.str.len + p2_len + 1); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); tn.addr = p2; tn.len = p2_len; s2pool(&tn); *stringpool.free++ = 0; compare.str.addr = c1; compare.str.len += sub.str.len + p2_len; STAT_FILE(compare.str.addr, &statbuf, stat_res); if (-1 == stat_res) continue; if (!(statbuf.st_mode & S_IFDIR)) continue; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) dir2, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } } CLOSEDIR(dp, closedir_res); } tmp = dir1; dir1 = dir2; dir2 = tmp; if (c >= top) break; } } else { sub.str.addr = pfil->l_dir; sub.str.len = pfil->b_dir; tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } if (wildname) { tn.addr = pfil->l_name; tn.len = pfil->b_name + pfil->b_ext; genpat(&tn, &pat_mval); } for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; if (wildname) { memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while(READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = strlen(&dent->d_name[0]); if ( dent->d_name[0] == '.' && (compare.str.len == 1 || (compare.str.len == 2 && dent->d_name[1] == '.'))) { continue; /* don't want to read . and .. */ } if (compare.str.len + sub.str.len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ if (stringpool.free + compare.str.len + sub.str.len > stringpool.top) stp_gcol(compare.str.len + sub.str.len); /* concatenate directory and name */ c = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); compare.str.addr = c; compare.str.len += sub.str.len; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) ind_var, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; plen = (plength *)&tmp->v.m[1]; plen->p.pblk.b_esl = compare.str.len; plen->p.pblk.b_dir = sub.str.len; for (c = &compare.str.addr[sub.str.len], c1 = top = &compare.str.addr[compare.str.len]; c < top; ) { if (*c++ != '.') break; } for (; c < top;) { if (*c++ == '.') c1 = c - 1; } plen->p.pblk.b_ext = top - c1; plen->p.pblk.b_name = plen->p.pblk.b_esl - plen->p.pblk.b_dir - plen->p.pblk.b_ext; } } CLOSEDIR(dp, closedir_res); } else { assert(pfil->fnb & F_WILD_DIR); compare.str.addr = pfil->l_name; compare.str.len = pfil->b_name + pfil->b_ext; if (compare.str.len + sub.str.len > MAX_FBUFF) continue; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; if (stringpool.free + compare.str.len + sub.str.len > stringpool.top) stp_gcol(compare.str.len + sub.str.len); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); compare.str.addr = c1; compare.str.len += sub.str.len; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) ind_var, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; plen = (plength *)&tmp->v.m[1]; plen->p.pblk.b_esl = compare.str.len; plen->p.pblk.b_dir = sub.str.len; plen->p.pblk.b_name = pfil->b_name; plen->p.pblk.b_ext = pfil->b_ext; } } op_kill(zsrch_dir1); op_kill(zsrch_dir2); REVERT; }
void zro_load (mstr *str) { unsigned toktyp, status; mstr tok; char *lp, *top; zro_ent array[ZRO_MAX_ENTS], *op; int oi, si, total_ents; struct stat outbuf; int stat_res; char tranbuf[MAX_FBUFF + 1]; parse_blk pblk; error_def (ERR_DIRONLY); error_def (ERR_FILEPARSE); error_def (ERR_FSEXP); error_def (ERR_MAXARGCNT); error_def (ERR_QUALEXP); error_def (ERR_ZROSYNTAX); error_def (ERR_NOLBRSRC); error_def (ERR_INVZROENT); lp = str->addr; top = lp + str->len; while (lp < top && *lp == ZRO_DEL) lp++; array[0].type = ZRO_TYPE_COUNT; array[0].count = 0; memset(&pblk, 0, sizeof(pblk)); pblk.buffer = tranbuf; GETTOK; if (toktyp == ZRO_EOL) { array[0].count = 1; array[1].type = ZRO_TYPE_OBJECT; array[1].str.len = 0; array[2].type = ZRO_TYPE_COUNT; array[2].count = 1; array[3] = array[1]; array[3].type = ZRO_TYPE_SOURCE; si = 4; } else { for (oi = 1;;) { if (toktyp != ZRO_IDN) rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP); if (oi + 1 >= ZRO_MAX_ENTS) rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); if (tok.len >= sizeof (tranbuf)) rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr); pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&tok, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, status); tranbuf[ pblk.b_esl ] = 0; STAT_FILE(tranbuf, &outbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, errno); if (S_ISREG(outbuf.st_mode)) { /* regular file - a shared library file */ array[oi].shrlib = fgn_getpak(tranbuf, ERROR); array[oi].type = ZRO_TYPE_OBJLIB; si = oi + 1; } else { if (!S_ISDIR(outbuf.st_mode)) rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_INVZROENT, 2, tok.len, tok.addr); array[oi].type = ZRO_TYPE_OBJECT; array[oi + 1].type = ZRO_TYPE_COUNT; si = oi + 2; } array[0].count++; array[oi].str = tok; GETTOK; if (toktyp == ZRO_LBR) { if (array[oi].type == ZRO_TYPE_OBJLIB) rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_NOLBRSRC); GETTOK; if (toktyp == ZRO_DEL) GETTOK; if (toktyp != ZRO_IDN && toktyp != ZRO_RBR) rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_QUALEXP); array[oi + 1].count = 0; for (;;) { if (toktyp == ZRO_RBR) break; if (toktyp != ZRO_IDN) rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP); if (si >= ZRO_MAX_ENTS) rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); if (tok.len >= sizeof (tranbuf)) rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr); pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&tok, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, status); tranbuf[ pblk.b_esl ] = 0; STAT_FILE(tranbuf, &outbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, errno); if (!S_ISDIR(outbuf.st_mode)) rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_DIRONLY, 2, tok.len, tok.addr); array[oi + 1].count++; array[si].type = ZRO_TYPE_SOURCE; array[si].str = tok; si++; GETTOK; if (toktyp == ZRO_DEL) GETTOK; } GETTOK; } else { if ((array[oi].type != ZRO_TYPE_OBJLIB) && (toktyp == ZRO_DEL || toktyp == ZRO_EOL)) { if (si >= ZRO_MAX_ENTS) rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); array[oi + 1].count = 1; array[si] = array[oi]; array[si].type = ZRO_TYPE_SOURCE; si++; } } if (toktyp == ZRO_EOL) break; if (toktyp == ZRO_DEL) GETTOK; else rts_error(VARLSTCNT(4) ERR_ZROSYNTAX, 2, str->len, str->addr); oi = si; } } total_ents = si; if (zro_root) { assert (zro_root->type == ZRO_TYPE_COUNT); oi = zro_root->count; assert (oi); for (op = zro_root + 1; oi-- > 0; ) { /* release space held by translated entries */ assert (op->type == ZRO_TYPE_OBJECT || op->type == ZRO_TYPE_OBJLIB); if (op->str.len) free(op->str.addr); if ((op++)->type == ZRO_TYPE_OBJLIB) continue; /* i.e. no sources for shared library */ assert (op->type == ZRO_TYPE_COUNT); si = (op++)->count; for ( ; si-- > 0; op++) { assert (op->type == ZRO_TYPE_SOURCE); if (op->str.len) free(op->str.addr); } } free (zro_root); } zro_root = (zro_ent *) malloc (total_ents * sizeof (zro_ent)); longcpy ((uchar_ptr_t)zro_root, (uchar_ptr_t)array, total_ents * sizeof (zro_ent)); assert (zro_root->type == ZRO_TYPE_COUNT); oi = zro_root->count; assert (oi); for (op = zro_root + 1; oi-- > 0; ) { assert (op->type == ZRO_TYPE_OBJECT || op->type == ZRO_TYPE_OBJLIB); if (op->str.len) { pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&op->str, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, op->str.len, op->str.addr, status); op->str.addr = (char *)malloc(pblk.b_esl); op->str.len = pblk.b_esl; memcpy(op->str.addr, pblk.buffer, pblk.b_esl); } if ((op++)->type == ZRO_TYPE_OBJLIB) continue; assert (op->type == ZRO_TYPE_COUNT); si = (op++)->count; for ( ; si-- > 0; op++) { assert (op->type == ZRO_TYPE_SOURCE); if (op->str.len) { pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&op->str, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, op->str.len, op->str.addr, status); op->str.addr = (char *)malloc(pblk.b_esl); op->str.len = pblk.b_esl; memcpy(op->str.addr, pblk.buffer, pblk.b_esl); } } } }
gd_region *dbfilopn (gd_region *reg) { unix_db_info *udi; parse_blk pblk; mstr file; char *fnptr, fbuff[MAX_FBUFF + 1]; struct stat buf; gd_region *prev_reg; gd_segment *seg; int status; bool raw; int stat_res; seg = reg->dyn.addr; assert(seg->acc_meth == dba_bg || seg->acc_meth == dba_mm); if (NULL == seg->file_cntl) { seg->file_cntl = (file_control *)malloc(sizeof(*seg->file_cntl)); memset(seg->file_cntl, 0, sizeof(*seg->file_cntl)); } if (NULL == seg->file_cntl->file_info) { seg->file_cntl->file_info = (void *)malloc(sizeof(unix_db_info)); memset(seg->file_cntl->file_info, 0, sizeof(unix_db_info)); } file.addr = (char *)seg->fname; file.len = seg->fname_len; memset(&pblk, 0, sizeof(pblk)); pblk.buffer = fbuff; pblk.buff_size = MAX_FBUFF; pblk.fop = (F_SYNTAXO | F_PARNODE); memcpy(fbuff,file.addr,file.len); *(fbuff + file.len) = '\0'; if (is_raw_dev(fbuff)) { raw = TRUE; pblk.def1_buf = DEF_NODBEXT; pblk.def1_size = sizeof(DEF_NODBEXT) - 1; } else { raw = FALSE; pblk.def1_buf = DEF_DBEXT; pblk.def1_size = sizeof(DEF_DBEXT) - 1; } status = parse_file(&file, &pblk); if (!(status & 1)) { if (GTCM_GNP_SERVER_IMAGE != image_type) { free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; } rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status); } assert(pblk.b_esl < sizeof(seg->fname)); memcpy(seg->fname, pblk.buffer, pblk.b_esl); pblk.buffer[pblk.b_esl] = 0; seg->fname[pblk.b_esl] = 0; seg->fname_len = pblk.b_esl; if (pblk.fnb & F_HAS_NODE) { /* Remote node specification given */ assert(pblk.b_node && pblk.l_node[pblk.b_node - 1] == ':'); gvcmy_open(reg, &pblk); return (gd_region *)-1; } fnptr = (char *)seg->fname + pblk.b_node; udi = FILE_INFO(reg); udi->raw = raw; udi->fn = (char *)fnptr; OPENFILE(fnptr, O_RDWR, udi->fd); udi->ftok_semid = INVALID_SEMID; udi->semid = INVALID_SEMID; udi->shmid = INVALID_SHMID; udi->sem_ctime = 0; udi->shm_ctime = 0; reg->read_only = FALSE; /* maintain csa->read_write simultaneously */ udi->s_addrs.read_write = TRUE; /* maintain reg->read_only simultaneously */ if (udi->fd == -1) { OPENFILE(fnptr, O_RDONLY, udi->fd); if (udi->fd == -1) { errno_save = errno; if (GTCM_GNP_SERVER_IMAGE != image_type) { free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; } rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), errno_save); } reg->read_only = TRUE; /* maintain csa->read_write simultaneously */ udi->s_addrs.read_write = FALSE; /* maintain reg->read_only simultaneously */ } STAT_FILE(fnptr, &buf, stat_res); set_gdid_from_stat(&udi->fileid, &buf); if (prev_reg = gv_match(reg)) { close(udi->fd); free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; return prev_reg; } return reg; }
/* Routine to parse the value of $ZROUTINES and create the list of structures that define the (new) routine * search list order and define which (if any) directories can use auto-relink. * * Parameter: * str - string to parse (usually dollar_zroutines) * * Return code: * none */ void zro_load(mstr *str) { unsigned toktyp, status; boolean_t enable_autorelink; mstr tok, transtr; char *lp, *top; zro_ent array[ZRO_MAX_ENTS], *op; int oi, si, total_ents; struct stat outbuf; int stat_res; char tranbuf[MAX_FBUFF + 1]; parse_blk pblk; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ARLINK_ONLY(TREF(arlink_enabled) = FALSE); /* Set if any zro entry is enabled for autorelink */ memset(array, 0, SIZEOF(array)); lp = str->addr; top = lp + str->len; while ((lp < top) && (ZRO_DEL == *lp)) /* Bypass leading blanks */ lp++; array[0].type = ZRO_TYPE_COUNT; array[0].count = 0; memset(&pblk, 0, SIZEOF(pblk)); pblk.buffer = tranbuf; toktyp = GETTOK; if (ZRO_EOL == toktyp) { /* Null string - set default - implies current working directory only */ array[0].count = 1; array[1].type = ZRO_TYPE_OBJECT; array[1].str.len = 0; array[2].type = ZRO_TYPE_COUNT; array[2].count = 1; array[3].type = ZRO_TYPE_SOURCE; array[3].str.len = 0; si = 4; } else { /* String supplied - parse it */ for (oi = 1;;) { if (ZRO_IDN != toktyp) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP); if (ZRO_MAX_ENTS <= (oi + 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); /* We have type ZRO_IDN (an identifier/name of some sort). See if token has a "*" (ZRO_ALF) at the end * of it indicating that it is supposed to (1) be a directory and not a shared library and (2) that the * user desires this directory to have auto-relink capability. */ enable_autorelink = FALSE; /* All platforms allow the auto-relink indicator on object directories but only autorelink able platforms * (#ifdef AUTORELINK_SUPPORTED is set) do anything with it. Other platforms just ignore it. Specifying * "*" at end of non-object directories causes an error further downstream (FILEPARSE) when the "*" is * not stripped off the file name - unless someone has managed to create a directory with a "*" suffix. */ if (ZRO_ALF == *(tok.addr + tok.len - 1)) { /* Auto-relink is indicated */ enable_autorelink = TRUE; TREF(arlink_enabled) = TRUE; --tok.len; /* Remove indicator from name so we can use it */ assert(0 <= tok.len); } if (SIZEOF(tranbuf) <= tok.len) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr); /* Run specified directory through parse_file to fill in any missing pieces and get some info on it */ pblk.buff_size = MAX_FBUFF; /* Don't count null terminator here */ pblk.fnb = 0; status = parse_file(&tok, &pblk); if (!(status & 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, status); tranbuf[pblk.b_esl] = 0; /* Needed for some subsequent STAT_FILE */ STAT_FILE(tranbuf, &outbuf, stat_res); if (-1 == stat_res) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, errno); if (S_ISREG(outbuf.st_mode)) { /* Regular file - a shared library file */ if (enable_autorelink) /* Auto-relink indicator on shared library not permitted */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr); array[oi].shrlib = zro_shlibs_find(tranbuf); array[oi].type = ZRO_TYPE_OBJLIB; si = oi + 1; } else { if (!S_ISDIR(outbuf.st_mode)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_INVZROENT, 2, tok.len, tok.addr); array[oi].type = ZRO_TYPE_OBJECT; array[oi + 1].type = ZRO_TYPE_COUNT; si = oi + 2; # ifdef AUTORELINK_SUPPORTED # ifdef DEBUG /* If env var gtm_test_autorelink_always is set in dbg version, treat every * object directory specified in $zroutines as if * has been additionally specified. */ if (TREF(gtm_test_autorelink_always)) { enable_autorelink = TRUE; TREF(arlink_enabled) = TRUE; } # endif if (enable_autorelink) { /* Only setup autorelink struct if it is enabled */ if (!TREF(is_mu_rndwn_rlnkctl)) { transtr.addr = tranbuf; transtr.len = pblk.b_esl; array[oi].relinkctl_sgmaddr = (void_ptr_t)relinkctl_attach(&transtr, NULL, 0); } else { /* If zro_load() is called as a part of MUPIP RUNDOWN -RELINKCTL, then we do not * want to do relinkctl_attach() on all relinkctl files at once because we leave * the function holding the linkctl lock, which might potentially cause a deadlock * if multiple processes are run concurrently with different $gtmroutines. However, * we need a way to tell mu_rndwn_rlnkctl() which object directories are autorelink- * enabled. For that we set a negative number to the presently unused count field of * object directory entries in the zro_ent linked list. If we ever decide to make * that value meaningful, then, perhaps, ensuring that this count remains negative * in case of MUPIP RUNDOWN -RELINKCTL but has the correct absolute value would do * the trick. */ array[oi].count = ZRO_DIR_ENABLE_AR; } } # endif } array[0].count++; array[oi].str = tok; toktyp = GETTOK; if (ZRO_LBR == toktyp) { if (ZRO_TYPE_OBJLIB == array[oi].type) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_NOLBRSRC); toktyp = GETTOK; if (ZRO_DEL == toktyp) toktyp = GETTOK; if ((ZRO_IDN != toktyp) && (ZRO_RBR != toktyp)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_QUALEXP); array[oi + 1].count = 0; for (;;) { if (ZRO_RBR == toktyp) break; if (ZRO_IDN != toktyp) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP); if (ZRO_MAX_ENTS <= si) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); if (SIZEOF(tranbuf) <= tok.len) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr); pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&tok, &pblk); if (!(status & 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, status); tranbuf[pblk.b_esl] = 0; STAT_FILE(tranbuf, &outbuf, stat_res); if (-1 == stat_res) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr, errno); if (!S_ISDIR(outbuf.st_mode)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_DIRONLY, 2, tok.len, tok.addr); array[oi + 1].count++; array[si].type = ZRO_TYPE_SOURCE; array[si].str = tok; si++; toktyp = GETTOK; if (ZRO_DEL == toktyp) toktyp = GETTOK; } toktyp = GETTOK; } else { if ((ZRO_TYPE_OBJLIB != array[oi].type) && ((ZRO_DEL == toktyp) || (ZRO_EOL == toktyp))) { if (ZRO_MAX_ENTS <= si) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS); array[oi + 1].count = 1; array[si] = array[oi]; array[si].type = ZRO_TYPE_SOURCE; si++; } } if (ZRO_EOL == toktyp) break; if (ZRO_DEL == toktyp) toktyp = GETTOK; else rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZROSYNTAX, 2, str->len, str->addr); oi = si; } } total_ents = si; if (TREF(zro_root)) { assert((TREF(zro_root))->type == ZRO_TYPE_COUNT); oi = (TREF(zro_root))->count; assert(oi); for (op = TREF(zro_root) + 1; 0 < oi--;) { /* Release space held by translated entries */ assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type)); if (op->str.len) free(op->str.addr); if (ZRO_TYPE_OBJLIB == (op++)->type) continue; /* i.e. no sources for shared library */ assert(ZRO_TYPE_COUNT == op->type); si = (op++)->count; for (; si-- > 0; op++) { assert(ZRO_TYPE_SOURCE == op->type); if (op->str.len) free(op->str.addr); } } free(TREF(zro_root)); } TREF(zro_root) = (zro_ent *)malloc(total_ents * SIZEOF(zro_ent)); memcpy((uchar_ptr_t)TREF(zro_root), (uchar_ptr_t)array, total_ents * SIZEOF(zro_ent)); assert(ZRO_TYPE_COUNT == (TREF(zro_root))->type); oi = (TREF(zro_root))->count; assert(oi); for (op = TREF(zro_root) + 1; 0 < oi--;) { assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type)); if (op->str.len) { pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&op->str, &pblk); if (!(status & 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, op->str.len, op->str.addr, status); op->str.addr = (char *)malloc(pblk.b_esl); op->str.len = pblk.b_esl; memcpy(op->str.addr, pblk.buffer, pblk.b_esl); } if (ZRO_TYPE_OBJLIB == (op++)->type) continue; assert(ZRO_TYPE_COUNT == op->type); si = (op++)->count; for (; 0 < si--; op++) { assert(ZRO_TYPE_SOURCE == op->type); if (op->str.len) { pblk.buff_size = MAX_FBUFF; pblk.fnb = 0; status = parse_file(&op->str, &pblk); if (!(status & 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, op->str.len, op->str.addr, status); op->str.addr = (char *)malloc(pblk.b_esl); op->str.len = pblk.b_esl; memcpy(op->str.addr, pblk.buffer, pblk.b_esl); } } } (TREF(set_zroutines_cycle))++; /* Signal need to recompute zroutines histories for each linked routine */ }
bool open_source_file (void) { mstr fstr; int status, n; parse_blk pblk; char *p, buff[MAX_FBUFF + 1]; time_t clock; struct stat statbuf; mval val; mval pars; unsigned short clen; memset(&pblk, 0, SIZEOF(pblk)); pblk.buffer = buff; pblk.buff_size = MAX_FBUFF; pblk.fop = F_SYNTAXO; fstr.addr = (char *)source_file_name; fstr.len = source_name_len; status = parse_file(&fstr, &pblk); if (!(status & 1)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status); pars.mvtype = MV_STR; pars.str.len = SIZEOF(open_params_list); pars.str.addr = (char *)open_params_list; val.mvtype = MV_STR; val.str.len = source_name_len; val.str.addr = (char *)source_file_name; op_open(&val, &pars, 0, 0); dev_in_use = io_curr_device; /* save list file info in use if it is opened */ op_use(&val, &pars); compile_src_dev = io_curr_device; if (tt_so_do_once) { clock = time(0); p = "MDEFAULT"; n = STR_LIT_LEN("MDEFAULT"); } else { STAT_FILE((char *)source_file_name, &statbuf, status); assert(status == 0); clock = statbuf.st_mtime; p = pblk.l_name; n = pblk.b_name; if (n > MAX_MIDENT_LEN) n = MAX_MIDENT_LEN; } /* routine_name is the internal name of the routine (with '%' translated to '_') which can be * different from module_name if the NAMEOFRTN parm is used (by trigger compilation code). * module_name is the external file name of the module (file.m, file.o). * int_module_name is the external symbol that gets exposed (in the GTM context) and is normally * the same as module_name except when NAMEOFRTN is specified in which case it takes on the * untranslated value of routine_name. */ memcpy(module_name.addr, p, n); module_name.len = n; if (!(cmd_qlf.qlf & CQ_NAMEOFRTN)) { memcpy(routine_name.addr, p, n); routine_name.len = n; } else { /* Routine name specified */ clen = MAX_MIDENT_LEN; cli_get_str("NAMEOFRTN", routine_name.addr, &clen); routine_name.len = MIN(clen, MAX_MIDENT_LEN); cmd_qlf.qlf &= ~CQ_NAMEOFRTN; /* Can only be used for first module in list */ } memcpy(int_module_name.addr, routine_name.addr, routine_name.len); int_module_name.len = routine_name.len; if ('_' == *routine_name.addr) routine_name.addr[0] = '%'; GTM_CTIME(p, &clock); memcpy(rev_time_buf, p + 4, REV_TIME_BUFF_LEN); io_curr_device = dev_in_use; /* set it back to make open_list_file save the device */ return TRUE; }
bool mubgetfil(backup_reg_list *list, char *name, unsigned short len) { struct stat stat_buf; int stat_res; char temp; char tcp[5]; if (0 == len) return FALSE; if (list != mu_repl_inst_reg_list) { /* Do the following checks only if this region does NOT correspond to the replication instance region. */ if ('|' == *name) { len -= 1; list->backup_to = backup_to_exec; list->backup_file.len = len; list->backup_file.addr = (char *)malloc(len + 1); memcpy(list->backup_file.addr, name + 1, len); return TRUE; } if (len > 5) { lower_to_upper((uchar_ptr_t)tcp, (uchar_ptr_t)name, 5); if (0 == memcmp(tcp, "TCP:/", 5)) { list->backup_to = backup_to_tcp; len -= 5; name += 5; while ('/' == *name) { len--; name++; } list->backup_file.len = len; list->backup_file.addr = (char *)malloc(len + 1); memcpy(list->backup_file.addr, name, len); *(list->backup_file.addr + len) = 0; return TRUE; } } } temp = name[len]; name[len] = 0; STAT_FILE(name, &stat_buf, stat_res); if (-1 == stat_res) { if (errno != ENOENT) { util_out_print("Error accessing backup output file or directory: !AD", TRUE, len, name); mupip_exit(errno); } else { /* new file */ list->backup_file.len = len; list->backup_file.addr = (char *)malloc(len + 1); memcpy(list->backup_file.addr, name, len); *(list->backup_file.addr + len) = 0; } } else if (S_ISDIR(stat_buf.st_mode)) { if (!is_directory) { is_directory = TRUE; directory.len = len; directory.addr = (char *)malloc(len + 1); memcpy(directory.addr, name, len); *(directory.addr + len) = 0; } mubexpfilnam(name, len, list); } else { /* the file already exists */ util_out_print("File !AD already exists.", TRUE, len, name); error_mupip = TRUE; return FALSE; } name[len] = temp; return TRUE; }
void dir_srch(parse_blk *pfil) { struct stat statbuf; int stat_res; lv_val *dir1, *dir2, *tmp; mstr tn; short p2_len; char filb[MAX_FBUFF + 1], patb[SIZEOF(ptstr)], *c, *lastd, *top, *p2, *c1, ch; mval pat_mval, sub, compare; boolean_t wildname, seen_wd; struct dirent *dent; DIR *dp; plength *plen; int closedir_res; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; op_kill(TREF(zsearch_dir1)); op_kill(TREF(zsearch_dir2)); if (!pfil->b_name) return; /* nothing to search for */ ESTABLISH(dir_ch); pat_mval.mvtype = MV_STR; pat_mval.str.addr = patb; /* patb should be SIZEOF(ptstr.buff) but instead is SIZEOF(ptstr) since the C compiler * complains about the former and the latter is just 4 bytes more */ pat_mval.str.len = 0; sub.mvtype = MV_STR; sub.str.len = 0; compare.mvtype = MV_STR; compare.str.len = 0; wildname = (pfil->fnb & F_WILD_NAME) != 0; dir1 = TREF(zsearch_dir1); dir2 = TREF(zsearch_dir2); if (pfil->fnb & F_WILD_DIR) { seen_wd = FALSE; for (c = pfil->l_dir, lastd = c, top = c + pfil->b_dir; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } assert(c <= top); sub.str.addr = pfil->l_dir; sub.str.len = INTCAST(lastd - sub.str.addr); tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; for (;;) { tn.addr = lastd; /* wildcard segment */ tn.len = INTCAST(c - lastd - 1); lastd = c; genpat(&tn, &pat_mval); seen_wd = FALSE; p2 = c - 1; for (; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } p2_len = lastd - p2; /* length of non-wild segment after wild section */ for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while (READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = STRLEN(&dent->d_name[0]); UNICODE_ONLY( if (gtm_utf8_mode) compare.mvtype &= ~MV_UTF_LEN; /* to force "char_len" to be recomputed * in do_pattern */ ) assert(compare.str.len); if (('.' == dent->d_name[0]) && ((1 == compare.str.len) || ((2 == compare.str.len) && ('.' == dent->d_name[1])))) continue; /* don't want to read . and .. */ if (compare.str.len + sub.str.len + p2_len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ ENSURE_STP_FREE_SPACE(compare.str.len + sub.str.len + p2_len + 1); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); tn.addr = p2; tn.len = p2_len; s2pool(&tn); *stringpool.free++ = 0; compare.str.addr = c1; compare.str.len += sub.str.len + p2_len; STAT_FILE(compare.str.addr, &statbuf, stat_res); if (-1 == stat_res) continue; if (!(statbuf.st_mode & S_IFDIR)) continue; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) dir2, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } } CLOSEDIR(dp, closedir_res); } tmp = dir1; dir1 = dir2; dir2 = tmp; if (c >= top) break; }
int op_fnzsearch(mval *file, mint indx, mval *ret) { struct stat statbuf; int stat_res; parse_blk pblk; plength *plen, pret; char buf1[MAX_FBUFF + 1]; /* buffer to hold translated name */ mval sub; mstr tn; lv_val *ind_tmp; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ESTABLISH_RET(fnzsrch_ch, -1); TREF(fnzsearch_nullsubs_sav) = TREF(lv_null_subs); TREF(lv_null_subs) = LVNULLSUBS_OK; /* $ZSearch processing depends on this */ MV_FORCE_STR(file); if (file->str.len > MAX_FBUFF) rts_error(VARLSTCNT(4) ERR_INVSTRLEN, 2, file->str.len, MAX_FBUFF); MV_FORCE_MVAL(((mval *)TADR(fnzsearch_sub_mval)), indx); TREF(fnzsearch_lv_vars) = op_srchindx(VARLSTCNT(2) TREF(zsearch_var), (mval *)TADR(fnzsearch_sub_mval)); if (TREF(fnzsearch_lv_vars)) { assert((TREF(fnzsearch_lv_vars))->v.mvtype & MV_STR); if ((file->str.len != (TREF(fnzsearch_lv_vars))->v.str.len) || memcmp(file->str.addr, (TREF(fnzsearch_lv_vars))->v.str.addr, file->str.len)) { op_kill(TREF(fnzsearch_lv_vars)); TREF(fnzsearch_lv_vars) = NULL; } } if (TREF(fnzsearch_lv_vars)) { for (;;) { pret.p.pint = pop_top(TREF(fnzsearch_lv_vars), ret); /* get next element off the top */ if (!ret->str.len) break; memcpy(buf1, ret->str.addr, ret->str.len); buf1[ret->str.len] = 0; STAT_FILE(buf1, &statbuf, stat_res); if (-1 == stat_res) { if (errno == ENOENT) continue; rts_error(VARLSTCNT(1) errno); } break; } } else { memset(&pblk, 0, SIZEOF(pblk)); pblk.buffer = buf1; pblk.buff_size = MAX_FBUFF; if (!(parse_file(&file->str, &pblk) & 1)) { ret->mvtype = MV_STR; ret->str.len = 0; } else { assert(!TREF(fnzsearch_lv_vars)); buf1[pblk.b_esl] = 0; /* establish new search context */ TREF(fnzsearch_lv_vars) = op_putindx(VARLSTCNT(2) TREF(zsearch_var), TADR(fnzsearch_sub_mval)); (TREF(fnzsearch_lv_vars))->v = *file; /* zsearch_var(indx)=original spec */ if (!(pblk.fnb & F_WILD)) { sub.mvtype = MV_STR; sub.str.len = pblk.b_esl; sub.str.addr = buf1; s2pool(&sub.str); ind_tmp = op_putindx(VARLSTCNT(2) TREF(fnzsearch_lv_vars), &sub); ind_tmp->v.mvtype = MV_STR; ind_tmp->v.str.len = 0; plen = (plength *)&ind_tmp->v.m[1]; plen->p.pblk.b_esl = pblk.b_esl; plen->p.pblk.b_dir = pblk.b_dir; plen->p.pblk.b_name = pblk.b_name; plen->p.pblk.b_ext = pblk.b_ext; } else dir_srch(&pblk); for (;;) { pret.p.pint = pop_top(TREF(fnzsearch_lv_vars), ret); /* get next element off the top */ if (!ret->str.len) break; memcpy(buf1, ret->str.addr, ret->str.len); buf1[ret->str.len] = 0; STAT_FILE(buf1, &statbuf, stat_res); if (-1 == stat_res) { if (errno == ENOENT) continue; rts_error(VARLSTCNT(1) errno); } break; } } } assert((0 == ret->str.len) || (pret.p.pblk.b_esl == ret->str.len)); TREF(lv_null_subs) = TREF(fnzsearch_nullsubs_sav); REVERT; return pret.p.pint; }
bool open_source_file (void) { static readonly unsigned char open_params_list[] = { (unsigned char)iop_readonly, (unsigned char)iop_eol }; mstr fstr; int status, n,index; parse_blk pblk; char *p, buff[MAX_FBUFF + 1]; time_t clock; struct stat statbuf; mval val; mval pars; error_def (ERR_FILEPARSE); memset(&pblk, 0, sizeof(pblk)); pblk.buffer = buff; pblk.buff_size = MAX_FBUFF; pblk.fop = F_SYNTAXO; fstr.addr = (char *)source_file_name; fstr.len = source_name_len; status = parse_file(&fstr, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status); pars.mvtype = MV_STR; pars.str.len = sizeof(open_params_list); pars.str.addr = (char *)open_params_list; val.mvtype = MV_STR; val.str.len = source_name_len; val.str.addr = (char *)source_file_name; op_open(&val, &pars, 0, 0); dev_in_use = io_curr_device; /* save list file info in use if it is opened */ op_use(&val, &pars); compile_src_dev = io_curr_device; if (tt_so_do_once) { clock = time(0); memcpy(&routine_name[0], "MDEFAULT", sizeof("MDEFAULT") - 1); memcpy(&module_name[0], "MDEFAULT", sizeof("MDEFAULT") - 1); } else { STAT_FILE((char *)&source_file_name[0], &statbuf, status); assert(status == 0); clock = statbuf.st_mtime; p = pblk.l_name; n = pblk.b_name; if (n > sizeof(mident)) n = sizeof(mident); index = 0; if ('_' == *p) { routine_name[index] = '%'; module_name[index] = '_'; p++; index++; } for (; index < n; index++) routine_name[index] = module_name[index] = *p++; for (; index < (sizeof(mident)); index++ ) routine_name[index] = module_name[index] = 0; } p = (char *)GTM_CTIME(&clock); memcpy (rev_time_buf, p + 4, sizeof(rev_time_buf)); io_curr_device = dev_in_use; /* set it back to make open_list_file save the device */ return TRUE; }
int op_fnzsearch (mval *file, mint indx, mval *ret) { struct stat statbuf; int stat_res; parse_blk pblk; plength *plen, pret; char buf1[MAX_FBUFF + 1]; /* buffer to hold translated name */ mval sub; mstr tn; lv_val *ind_tmp; error_def(ERR_INVSTRLEN); MV_FORCE_STR(file); if (file->str.len > MAX_FBUFF) rts_error(VARLSTCNT(4) ERR_INVSTRLEN, 2, file->str.len, MAX_FBUFF); MV_FORCE_MVAL(&ind_val, indx); ind_var = op_srchindx(VARLSTCNT(2) zsrch_var, &ind_val); if (ind_var) { assert(ind_var->v.mvtype & MV_STR); if (file->str.len != ind_var->v.str.len || memcmp(file->str.addr, ind_var->v.str.addr, file->str.len)) { op_kill(ind_var); ind_var = (lv_val*) 0; } } if (ind_var) { for (;;) { pret.p.pint = pop_top(ind_var, ret); /* get next element off the top */ if (!ret->str.len) break; memcpy(buf1, ret->str.addr, ret->str.len); buf1[ret->str.len] = 0; STAT_FILE(buf1, &statbuf, stat_res); if (-1 == stat_res) { if (errno == ENOENT) continue; rts_error(VARLSTCNT(1) errno); } break; } } else { memset(&pblk, 0, sizeof(pblk)); pblk.buffer = buf1; pblk.buff_size = MAX_FBUFF; if (!(parse_file(&file->str, &pblk) & 1)) { ret->mvtype = MV_STR; ret->str.len = 0; } else { assert(!ind_var); buf1[pblk.b_esl] = 0; /* establish new search context */ ind_var = op_putindx(VARLSTCNT(2) zsrch_var, &ind_val); ind_var->v = *file; /* zsrch_var(indx)=original spec */ if (!(pblk.fnb & F_WILD)) { sub.mvtype = MV_STR; sub.str.len = pblk.b_esl; sub.str.addr = buf1; s2pool(&sub.str); ind_tmp = op_putindx(VARLSTCNT(2) ind_var, &sub); ind_tmp->v.mvtype = MV_STR; ind_tmp->v.str.len = 0; plen = (plength *)&ind_tmp->v.m[1]; plen->p.pblk.b_esl = pblk.b_esl; plen->p.pblk.b_dir = pblk.b_dir; plen->p.pblk.b_name = pblk.b_name; plen->p.pblk.b_ext = pblk.b_ext; } else dir_srch(&pblk); for (;;) { pret.p.pint = pop_top(ind_var, ret); /* get next element off the top */ if (!ret->str.len) break; memcpy(buf1, ret->str.addr, ret->str.len); buf1[ret->str.len] = 0; STAT_FILE(buf1, &statbuf, stat_res); if (-1 == stat_res) { if (errno == ENOENT) continue; rts_error(VARLSTCNT(1) errno); } break; } } } assert(pret.p.pblk.b_esl == ret->str.len); return pret.p.pint; }
cm_region_head *gtcmd_ini_reg(connection_struct *cnx) { cm_region_head *ptr,*last; struct stat stat_buf; unsigned char *fname, buff[256]; unsigned short len; uint4 status, retlen; unsigned char node[MAX_HOST_NAME_LEN]; sgmnt_addrs *csa; error_def (ERR_DBOPNERR); ptr = 0; fname = cnx->clb_ptr->mbf; fname++; GET_USHORT(len, fname); /* len = *((unsigned short *)fname); */ fname += sizeof(unsigned short); buff[len] = 0; memcpy(buff, fname, len); STAT_FILE((char *)buff, &stat_buf, status); if (-1 == status) rts_error(VARLSTCNT(5) ERR_DBOPNERR, 2, len, fname, errno); last = reglist; for (ptr = reglist ; ptr ; ptr = ptr->next) { if (is_gdid_stat_identical(&FILE_INFO(ptr->reg)->fileid, &stat_buf)) break; last = ptr; } if (!ptr) { /* open region */ ptr = (cm_region_head*)malloc(sizeof(*ptr)); ptr->next = NULL; ptr->last = NULL; ptr->head.fl = ptr->head.bl = 0; SET_LATCH_GLOBAL(&ptr->head.latch, LOCK_AVAILABLE); if (!last) reglist = ptr; else { last->next = ptr; ptr->last = last; } mu_gv_cur_reg_init(); ptr->reg = gv_cur_region; ptr->refcnt = 0; ptr->wakeup = 0; ptr->reg->open = FALSE; csa = &FILE_INFO(ptr->reg)->s_addrs; csa->now_crit = FALSE; csa->nl = (node_local_ptr_t)malloc(sizeof(node_local)); assert(MAX_FN_LEN > len); memcpy(ptr->reg->dyn.addr->fname, fname, len); ptr->reg->dyn.addr->fname_len = len; set_gdid_from_stat(&FILE_INFO(ptr->reg)->fileid, &stat_buf); ptr->reg_hash = (htab_desc *)malloc(sizeof(htab_desc)); if (-1 != gethostname((char *)node, sizeof(node))) { retlen = strlen((char *)node); retlen = MIN(retlen, MAX_RN_LEN - 1); memcpy(ptr->reg->rname, node, retlen); } else retlen = 0; ptr->reg->rname[retlen] = ':'; ptr->reg->rname_len = retlen + 1; gtcmd_cst_init(ptr); } else if (!ptr->reg->open) { gv_cur_region = ptr->reg; ptr->wakeup = 0; /* Because going to reinit ctl->wakeups when open region */ gtcmd_cst_init(ptr); } else gv_cur_region = ptr->reg; return ptr; }
int4 parse_file(mstr *file, parse_blk *pblk) { struct stat statbuf; struct addrinfo *ai_ptr, *localhost_ai_ptr, *temp_ai_ptr, hints; mstr trans, tmp; int status, diff, local_node_len, query_node_len, node_name_len; parse_blk def; char local_node_name[MAX_HOST_NAME_LEN + 1], query_node_name[MAX_HOST_NAME_LEN + 1]; char *base, *ptr, *top, *del, *node, *name, *ext, ch; char **hostaddrlist; char def_string[MAX_FBUFF + 1]; boolean_t hasnode, hasdir, hasname, hasext, wilddir, wildname; enum parse_state state; struct sockaddr_storage query_sas; struct sockaddr localhost_sa, *localhost_sa_ptr; mval def_trans; int errcode; pblk->fnb = 0; ai_ptr = localhost_ai_ptr = temp_ai_ptr = NULL; assert(((unsigned int)pblk->buff_size + 1) <= (MAX_FBUFF + 1)); /* All callers of parse_blk set buff_size to 1 less than the allocated buffer. This is because buff_size is a char * type (for historical reasons) and so cannot go more than 255 whereas we support a max of 255 characters. So we * allocate buffers that contain one more byte (for the terminating '\0') but dont set that in buff_size. Use * that extra byte for the trans_log_name call. */ status = TRANS_LOG_NAME(file, &trans, pblk->buffer, pblk->buff_size + 1, dont_sendmsg_on_log2long); if (SS_LOG2LONG == status) return ERR_PARBUFSM; assert(trans.addr == pblk->buffer); memset(&def, 0, SIZEOF(def)); /* Initial the defaults to zero */ if (pblk->def1_size > 0) { /* Parse default filespec if supplied */ def.fop = F_SYNTAXO; def.buffer = def_string; def.buff_size = MAX_FBUFF; def.def1_size = pblk->def2_size; def.def1_buf = pblk->def2_buf; tmp.len = pblk->def1_size; tmp.addr = pblk->def1_buf; if ((status = parse_file(&tmp, &def)) != ERR_PARNORMAL) return status; assert(!def.b_node); if (def.b_dir) def.fnb |= F_HAS_DIR; if (def.b_name) def.fnb |= F_HAS_NAME; if (def.b_ext) def.fnb |= F_HAS_EXT; } wildname = wilddir = hasnode = hasdir = hasname = hasext = FALSE; node = base = ptr = trans.addr; top = ptr + trans.len; if ((0 == trans.len) || ('/' != *ptr)) { /* No file given, no full path given, or a nodename was specified */ setzdir(NULL, &def_trans); /* Default current directory if none given */ assert((0 == dollar_zdir.str.len) /* dollar_zdir not initialized yet, possible thru main() -> gtm_chk_dist() */ || ((def_trans.str.len == dollar_zdir.str.len) /* Check if cwd and cached value are the same */ && (0 == memcmp(def_trans.str.addr, dollar_zdir.str.addr, def_trans.str.len)))); if (pblk->fop & F_PARNODE) { /* What we have could be a nodename */ assert(pblk->fop & F_SYNTAXO); while (node < top) { ch = *node++; if (':' == ch) /* We have nodeness */ break; if ('/' == ch) { /* Not a node - bypass node checking */ node = top; break; } } if (node < top) { hasnode = TRUE; ptr = base = node; /* Update pointers past node name */ /* See if the desired (query) node is the local node */ node_name_len = (int)(node - trans.addr); /* Scanned node including ':' */ query_node_len = node_name_len - 1; /* Pure name length, no ':' on end */ assert(MAX_HOST_NAME_LEN >= query_node_len); assert(0 < query_node_len); assert(':' == *(trans.addr + query_node_len)); memcpy(query_node_name, trans.addr, query_node_len); query_node_name[query_node_len] = 0; localhost_sa_ptr = NULL; /* Null value needed if not find query node (remote default) */ CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(query_node_name, NULL, &hints, &ai_ptr))) /* Assignment! */ ai_ptr = NULL; /* Skip additional lookups */ else memcpy((sockaddr_ptr)&query_sas, ai_ptr->ai_addr, ai_ptr->ai_addrlen); CLIENT_HINTS(hints); if (0 == (errcode = getaddrinfo(LOCALHOSTNAME, NULL, &hints, &localhost_ai_ptr)) && (0 == memcmp(localhost_ai_ptr->ai_addr, (sockaddr_ptr)&query_sas, localhost_ai_ptr->ai_addrlen))) { localhost_sa_ptr = localhost_ai_ptr->ai_addr; } FREEADDRINFO(localhost_ai_ptr); if (ai_ptr && !localhost_sa_ptr) { /* Have not yet established this is not a local node -- check further */ GETHOSTNAME(local_node_name, MAX_HOST_NAME_LEN, status); if (-1 == status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("gethostname"), CALLFROM, errno); CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(local_node_name, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (ai_ptr && !localhost_sa_ptr) { CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(LOCALHOSTNAME6, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (!localhost_sa_ptr) /* Not local (or an unknown) host given */ { /* Remote node specified -- don't apply any defaults */ FREEADDRINFO(ai_ptr); pblk->l_node = trans.addr; pblk->b_node = node_name_len; pblk->l_dir = base; pblk->b_dir = top - base; pblk->l_name = pblk->l_ext = base + pblk->b_dir; pblk->b_esl = pblk->b_node + pblk->b_dir; pblk->b_name = pblk->b_ext = 0; pblk->fnb |= (hasnode << V_HAS_NODE); return ERR_PARNORMAL; } FREEADDRINFO(ai_ptr); /* Remove local node name from filename buffer */ assert(0 < trans.len - node_name_len); memmove(trans.addr, node, trans.len - node_name_len); ptr = base = node -= node_name_len; top -= node_name_len; trans.len -= node_name_len; if ('/' == *base) /* No default directory if full path given */ def_trans.str.len = 0; } else { /* Supplied text was not a node -- reset pointer back to beginning for rescan */ node = trans.addr; } } /* If parse buffer is not large enough, return error */ if (def_trans.str.len + trans.len > pblk->buff_size) return ERR_PARBUFSM; /* Construct full filename to parse prefixing given filename with default path prefix */ if (0 < def_trans.str.len) { memmove(ptr + def_trans.str.len, ptr, trans.len); memcpy(ptr, def_trans.str.addr, def_trans.str.len); assert('/' == ptr[def_trans.str.len - 1]); ptr += def_trans.str.len; top += def_trans.str.len; } } name = ptr; state = NOSTATE; for (; ptr < top;) { ch = *ptr; if ('.' == ch) { /* Could be /./ or /../ or name.name */ ptr++; state = (DOT1 == state) ? ((DOT2 == state) ? NAME : DOT2) : DOT1; } else if (ch == '/') { /* We must still be doing the path */ ptr++; hasdir = TRUE; hasname = FALSE; hasext = FALSE; wilddir |= wildname; wildname = FALSE; if ((DOT1 != state) && (DOT2 != state) && (SLASH != state)) { /* No dots seen recently so scan as if this is start of filename */ state = SLASH; name = ptr; continue; } if (DOT1 == state) { /* Just remove "./" chars from path */ del = ptr - 2; } else if (DOT2 == state) { /* Have xx/../ construct. Remove /../ and previous level directory from path */ del = ptr - 4; /* /../ characters being removed */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; } else if (SLASH == state) { /* Remove duplicate slash from path */ del = ptr - 1; while ((ptr < top) && ('/' == *ptr)) ptr++; } memmove(del, ptr, top - ptr); diff = (int)(ptr - del); ptr -= diff; top -= diff; state = SLASH; name = ptr; } else { /* Hopeful of filename */ hasname = TRUE; while (ptr < top) /* Do small scan looking for filename end */ { ch = *ptr; if ('/' == ch) break; /* Ooops, still doing path */ if ('.' == ch) {/* Filename has an extension */ hasext = TRUE; ext = ptr; } else if (('?' == ch) || ('*' == ch)) wildname = TRUE; ptr++; } state = NAME; } } /* Handle scan end with non-normal state */ if ((SLASH == state) || (DOT1 == state) || (DOT2 == state)) { assert(!hasname && !hasext); hasdir = TRUE; if (state == DOT1) { /* Ignore ./ */ top--; ptr--; } if (DOT2 == state) { /* Ignore ../ plus last directory level specified */ del = ptr - 3; /* on the end */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; ptr = top = del; name = ptr; } } if (!hasname) { assert(!hasext); name = ptr; if (def.fnb & F_HAS_NAME) { /* Use default filename if we didn't find one */ diff = (int)(name - node); if (def.b_name + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(name, def.l_name, def.b_name); ptr += def.b_name; } ext = ptr; } if (!hasext) { ext = ptr; if (def.fnb & F_HAS_EXT) { /* Use default file extension if we didn't find one */ diff = (int)((ext - node)); if (def.b_ext + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(ext, def.l_ext, def.b_ext); ptr += def.b_ext; } } pblk->b_name = ext - name; pblk->b_ext = ptr - ext; if (!hasdir && (def.fnb & F_HAS_DIR)) { diff = (int)(name - base); diff = def.b_dir - diff; if (def.b_dir + pblk->b_name + pblk->b_ext > pblk->buff_size) return ERR_PARBUFSM; if (diff > 0) memmove(name + diff, name, pblk->b_name + pblk->b_ext); else if (diff < 0) memcpy(name + diff, name, pblk->b_name + pblk->b_ext); memcpy(base, def.l_dir, def.b_dir); ptr += diff; name += diff; } pblk->b_dir = name - base; pblk->b_esl = ptr - base; pblk->l_dir = base; pblk->l_name = base + pblk->b_dir; pblk->l_ext = pblk->l_name + pblk->b_name; pblk->fnb |= (hasdir << V_HAS_DIR); pblk->fnb |= (hasname << V_HAS_NAME); pblk->fnb |= (hasext << V_HAS_EXT); pblk->fnb |= (wildname << V_WILD_NAME); pblk->fnb |= (wilddir << V_WILD_DIR); if (!(pblk->fop & F_SYNTAXO) && !wilddir) { assert('/' == pblk->l_dir[pblk->b_dir - 1]); if (pblk->b_dir > 1) { pblk->l_dir[pblk->b_dir - 1] = 0; STAT_FILE(pblk->l_dir, &statbuf, status); pblk->l_dir[pblk->b_dir - 1] = '/'; if ((-1 == status) || !(statbuf.st_mode & S_IFDIR)) return ERR_FILENOTFND; } } return ERR_PARNORMAL; }
void iorm_close(io_desc *iod, mval *pp) { d_rm_struct *rm_ptr; unsigned char c; char *path, *path2; int fclose_res; int stat_res; int fstat_res; struct stat statbuf, fstatbuf; int p_offset; assert (iod->type == rm); if (iod->state != dev_open) return; rm_ptr = (d_rm_struct *)iod->dev_sp; iorm_use(iod,pp); if (iod->dollar.x && rm_ptr->lastop == RM_WRITE && !iod->dollar.za) iorm_flush(iod); p_offset = 0; while (*(pp->str.addr + p_offset) != iop_eol) { switch (c = *(pp->str.addr + p_offset++)) { case iop_delete: path = iod->trans_name->dollar_io; FSTAT_FILE(rm_ptr->fildes, &fstatbuf, fstat_res); if (-1 == fstat_res) rts_error(VARLSTCNT(1) errno); STAT_FILE(path, &statbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(1) errno); if (fstatbuf.st_ino == statbuf.st_ino) if (UNLINK(path) == -1) rts_error(VARLSTCNT(1) errno); break; case iop_rename: path = iod->trans_name->dollar_io; path2 = (char*)(pp->str.addr + p_offset + 1); FSTAT_FILE(rm_ptr->fildes, &fstatbuf, fstat_res); if (-1 == fstat_res) rts_error(VARLSTCNT(1) errno); STAT_FILE(path, &statbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(1) errno); if (fstatbuf.st_ino == statbuf.st_ino) { if (LINK(path, path2) == -1) rts_error(VARLSTCNT(1) errno); if (UNLINK(path) == -1) rts_error(VARLSTCNT(1) errno); } break; default: break; } p_offset += ( io_params_size[c]==IOP_VAR_SIZE ? (unsigned char)(*(pp->str.addr + p_offset) + 1) : io_params_size[c] ); } if (iod->pair.in != iod) assert (iod->pair.out == iod); if (iod->pair.out != iod) assert (iod->pair.in == iod); iod->state = dev_closed; iod->dollar.zeof = FALSE; iod->dollar.x = 0; iod->dollar.y = 0; rm_ptr->lastop = RM_NOOP; /* Do the close first. If the fclose() is done first and we are being called from io_rundown just prior to the execv in a newly JOBbed off process, the fclose() does an implied fflush() which is known to do an lseek() which resets the file pointers of any open (flat) files in the parent due to an archane interaction between child and parent processes prior to an execv() call. The fclose (for stream files) will fail but it will clean up structures orphaned by the close(). */ close(rm_ptr->fildes); if (rm_ptr->filstr != NULL) FCLOSE(rm_ptr->filstr, fclose_res); #ifdef __MVS__ if (rm_ptr->fifo) { if (rm_ptr != (iod->pair.out)->dev_sp || rm_ptr != (iod->pair.in)->dev_sp) { if (rm_ptr != (iod->pair.out)->dev_sp) { rm_ptr = (iod->pair.out)->dev_sp; iod = iod->pair.out; } else { rm_ptr = (iod->pair.in)->dev_sp; iod = iod->pair.in; } assert(NULL != rm_ptr); if(dev_closed != iod->state) { iod->state = dev_closed; iod->dollar.zeof = FALSE; iod->dollar.x = 0; iod->dollar.y = 0; rm_ptr->lastop = RM_NOOP; assert(rm_ptr->fildes>=0); close(rm_ptr->fildes); if (rm_ptr->filstr != NULL) fclose(rm_ptr->filstr); } } } #endif return; }
void mu_extract(void) { int stat_res, truncate_res; int reg_max_rec, reg_max_key, reg_max_blk, reg_std_null_coll; int iter, format, local_errno, int_nlen; boolean_t freeze = FALSE, logqualifier, success; char format_buffer[FORMAT_STR_MAX_SIZE], ch_set_name[MAX_CHSET_NAME], cli_buff[MAX_LINE], label_buff[LABEL_STR_MAX_SIZE], gbl_name_buff[MAX_MIDENT_LEN + 2]; /* 2 for null and '^' */ glist gl_head, *gl_ptr; gd_region *reg, *region_top; mu_extr_stats global_total, grand_total; uint4 item_code, devbufsiz, maxfield; unsigned short label_len, n_len, ch_set_len, buflen; unsigned char *outbuf, *outptr, *chptr, *leadptr; struct stat statbuf; mval val, curr_gbl_name, op_val, op_pars; mstr chset_mstr; gtm_chset_t saved_out_set; static unsigned char ochset_set = FALSE; static readonly unsigned char open_params_list[] = { (unsigned char)iop_noreadonly, (unsigned char)iop_nowrap, (unsigned char)iop_stream, (unsigned char)iop_eol }; static readonly unsigned char no_param = (unsigned char)iop_eol; coll_hdr extr_collhdr; error_def(ERR_NOSELECT); error_def(ERR_GTMASSERT); error_def(ERR_EXTRACTCTRLY); error_def(ERR_EXTRACTFILERR); error_def(ERR_MUPCLIERR); error_def(ERR_MUNOACTION); error_def(ERR_MUNOFINISH); error_def(ERR_RECORDSTAT); error_def(ERR_NULLCOLLDIFF); /* Initialize all local character arrays to zero before using */ memset(cli_buff, 0, sizeof(cli_buff)); memset(outfilename, 0, sizeof(outfilename)); memset(label_buff, 0, sizeof(label_buff)); memset(format_buffer, 0, sizeof(format_buffer)); active_device = io_curr_device.out; mu_outofband_setup(); if (CLI_PRESENT == cli_present("OCHSET")) { ch_set_len = sizeof(ch_set_name); if (cli_get_str("OCHSET", ch_set_name, &ch_set_len)) { if (0 == ch_set_len) mupip_exit(ERR_MUNOACTION); /* need to change to OPCHSET error when added */ ch_set_name[ch_set_len] = '\0'; #ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != active_device->output_conv_cd) ICONV_CLOSE_CD(active_device->output_conv_cd); if (DEFAULT_CODE_SET != active_device->out_code_set) ICONV_OPEN_CD(active_device->output_conv_cd, INSIDE_CH_SET, ch_set_name); #else chset_mstr.addr = ch_set_name; chset_mstr.len = ch_set_len; SET_ENCODING(active_device->ochset, &chset_mstr); get_chset_desc(&chset_names[active_device->ochset]); #endif ochset_set = TRUE; } } logqualifier = (CLI_NEGATED != cli_present("LOG")); if (CLI_PRESENT == cli_present("FREEZE")) freeze = TRUE; n_len = sizeof(format_buffer); if (FALSE == cli_get_str("FORMAT", format_buffer, &n_len)) { n_len = sizeof("ZWR") - 1; memcpy(format_buffer, "ZWR", n_len); } int_nlen = n_len; lower_to_upper((uchar_ptr_t)format_buffer, (uchar_ptr_t)format_buffer, int_nlen); if (0 == memcmp(format_buffer, "ZWR", n_len)) format = MU_FMT_ZWR; else if (0 == memcmp(format_buffer, "GO", n_len)) { if (gtm_utf8_mode) { util_out_print("Extract error: GO format is not supported in UTF-8 mode. Use ZWR format.", TRUE); mupip_exit(ERR_MUPCLIERR); } format = MU_FMT_GO; } else if (0 == memcmp(format_buffer, "BINARY", n_len)) format = MU_FMT_BINARY; else { util_out_print("Extract error: bad format type", TRUE); mupip_exit(ERR_MUPCLIERR); } n_len = sizeof(cli_buff); if (FALSE == cli_get_str((char *)select_text, cli_buff, &n_len)) { n_len = 1; cli_buff[0] = '*'; } /* gv_select will select globals */ gv_select(cli_buff, n_len, freeze, (char *)select_text, &gl_head, ®_max_rec, ®_max_key, ®_max_blk); if (!gl_head.next) { rts_error(VARLSTCNT(1) ERR_NOSELECT); mupip_exit(ERR_NOSELECT); } /* For binary format, check whether all regions have same null collation order */ if (MU_FMT_BINARY == format) { for (reg = gd_header->regions, region_top = gd_header->regions + gd_header->n_regions, reg_std_null_coll = -1; reg < region_top ; reg++) { if (reg->open) { if (reg_std_null_coll != reg->std_null_coll) { if (reg_std_null_coll == -1) reg_std_null_coll = reg->std_null_coll; else { rts_error(VARLSTCNT(1) ERR_NULLCOLLDIFF); mupip_exit(ERR_NULLCOLLDIFF); } } } } assert(-1 != reg_std_null_coll); } grand_total.recknt = grand_total.reclen = grand_total.keylen = grand_total.datalen = 0; global_total.recknt = global_total.reclen = global_total.keylen = global_total.datalen = 0; n_len = sizeof(outfilename); if (FALSE == cli_get_str("FILE", outfilename, &n_len)) { rts_error(VARLSTCNT(1) ERR_MUPCLIERR); mupip_exit(ERR_MUPCLIERR); } if (-1 == Stat((char *)outfilename, &statbuf)) { if (ENOENT != errno) { local_errno = errno; perror("Error opening output file"); mupip_exit(local_errno); } } else { util_out_print("Error opening output file: !AD -- File exists", TRUE, n_len, outfilename); mupip_exit(ERR_MUNOACTION); } op_pars.mvtype = MV_STR; op_pars.str.len = sizeof(open_params_list); op_pars.str.addr = (char *)open_params_list; op_val.mvtype = MV_STR; op_val.str.len = filename_len = n_len; op_val.str.addr = (char *)outfilename; (*op_open_ptr)(&op_val, &op_pars, 0, 0); ESTABLISH(mu_extract_handler); op_use(&op_val, &op_pars); if (MU_FMT_BINARY == format) { /* binary header label format: * fixed length text, fixed length date & time, * fixed length max blk size, fixed length max rec size, fixed length max key size, fixed length std_null_coll * 32-byte padded user-supplied string */ outbuf = (unsigned char *)malloc(sizeof(BIN_HEADER_LABEL) + sizeof(BIN_HEADER_DATEFMT) - 1 + 4 * BIN_HEADER_NUMSZ + BIN_HEADER_LABELSZ); outptr = outbuf; MEMCPY_LIT(outptr, BIN_HEADER_LABEL); outptr += STR_LIT_LEN(BIN_HEADER_LABEL); stringpool.free = stringpool.base; op_horolog(&val); stringpool.free = stringpool.base; op_fnzdate(&val, (mval *)&mu_bin_datefmt, &null_str, &null_str, &val); memcpy(outptr, val.str.addr, val.str.len); outptr += val.str.len; WRITE_NUMERIC(reg_max_blk); WRITE_NUMERIC(reg_max_rec); WRITE_NUMERIC(reg_max_key); WRITE_NUMERIC(reg_std_null_coll); if (gtm_utf8_mode) { MEMCPY_LIT(outptr, UTF8_NAME); label_len = STR_LIT_LEN(UTF8_NAME); outptr[label_len++] = ' '; } else label_len = 0; buflen = sizeof(label_buff); if (FALSE == cli_get_str("LABEL", label_buff, &buflen)) { MEMCPY_LIT(&outptr[label_len], EXTR_DEFAULT_LABEL); buflen = STR_LIT_LEN(EXTR_DEFAULT_LABEL); } else memcpy(&outptr[label_len], label_buff, buflen); label_len += buflen; if (label_len > BIN_HEADER_LABELSZ) { /* Label size exceeds the space, so truncate the label and back off to the valid beginning (i.e. to the leading byte) of the last character that can entirely fit in the space */ label_len = BIN_HEADER_LABELSZ; chptr = &outptr[BIN_HEADER_LABELSZ]; UTF8_LEADING_BYTE(chptr, outptr, leadptr); assert(chptr - leadptr < 4); if (leadptr < chptr) label_len -= (chptr - leadptr); } outptr += label_len; for (iter = label_len; iter < BIN_HEADER_LABELSZ; iter++) *outptr++ = ' '; label_len = outptr - outbuf; if (!ochset_set) { #ifdef KEEP_zOS_EBCDIC /* extract ascii header for binary by default */ /* Do we need to restore it somewhere? */ saved_out_set = (io_curr_device.out)->out_code_set; (io_curr_device.out)->out_code_set = DEFAULT_CODE_SET; #else saved_out_set = (io_curr_device.out)->ochset; (io_curr_device.out)->ochset = CHSET_M; #endif } op_val.str.addr = (char *)(&label_len); op_val.str.len = sizeof(label_len); op_write(&op_val); op_val.str.addr = (char *)outbuf; op_val.str.len = label_len; op_write(&op_val); } else { assert((MU_FMT_GO == format) || (MU_FMT_ZWR == format)); label_len = sizeof(label_buff); if (FALSE == cli_get_str("LABEL", label_buff, &label_len)) { MEMCPY_LIT(label_buff, EXTR_DEFAULT_LABEL); label_len = STR_LIT_LEN(EXTR_DEFAULT_LABEL); } if (gtm_utf8_mode) { label_buff[label_len++] = ' '; MEMCPY_LIT(&label_buff[label_len], UTF8_NAME); label_len += STR_LIT_LEN(UTF8_NAME); } label_buff[label_len++] = '\n'; op_val.mvtype = MV_STR; op_val.str.len = label_len; op_val.str.addr = label_buff; op_write(&op_val); stringpool.free = stringpool.base; op_horolog(&val); stringpool.free = stringpool.base; op_fnzdate(&val, &datefmt, &null_str, &null_str, &val); op_val = val; op_val.mvtype = MV_STR; op_write(&op_val); if (MU_FMT_ZWR == format) { op_val.str.addr = " ZWR"; op_val.str.len = sizeof(" ZWR") - 1; op_write(&op_val); } op_wteol(1); } REVERT; ESTABLISH(mu_extract_handler1); success = TRUE; for (gl_ptr = gl_head.next; gl_ptr; gl_ptr = gl_ptr->next) { if (mu_ctrly_occurred) break; if (mu_ctrlc_occurred) { gbl_name_buff[0]='^'; memcpy(&gbl_name_buff[1], gl_ptr->name.str.addr, gl_ptr->name.str.len); gtm_putmsg(VARLSTCNT(8) ERR_RECORDSTAT, 6, gl_ptr->name.str.len + 1, gbl_name_buff, global_total.recknt, global_total.keylen, global_total.datalen, global_total.reclen); mu_ctrlc_occurred = FALSE; } gv_bind_name(gd_header, &gl_ptr->name.str); if (MU_FMT_BINARY == format) { label_len = sizeof(extr_collhdr); op_val.mvtype = MV_STR; op_val.str.addr = (char *)(&label_len); op_val.str.len = sizeof(label_len); op_write(&op_val); extr_collhdr.act = gv_target->act; extr_collhdr.nct = gv_target->nct; extr_collhdr.ver = gv_target->ver; op_val.str.addr = (char *)(&extr_collhdr); op_val.str.len = sizeof(extr_collhdr); op_write(&op_val); } /* Note: Do not change the order of the expression below. * Otherwise if success is FALSE, mu_extr_gblout() will not be called at all. * We want mu_extr_gblout() to be called irrespective of the value of success */ success = mu_extr_gblout(&gl_ptr->name, &global_total, format) && success; if (logqualifier) { gbl_name_buff[0]='^'; memcpy(&gbl_name_buff[1], gl_ptr->name.str.addr, gl_ptr->name.str.len); gtm_putmsg(VARLSTCNT(8) ERR_RECORDSTAT, 6, gl_ptr->name.str.len + 1, gbl_name_buff, global_total.recknt, global_total.keylen, global_total.datalen, global_total.reclen); mu_ctrlc_occurred = FALSE; } grand_total.recknt += global_total.recknt; if (grand_total.reclen < global_total.reclen) grand_total.reclen = global_total.reclen; if (grand_total.keylen < global_total.keylen) grand_total.keylen = global_total.keylen; if (grand_total.datalen < global_total.datalen) grand_total.datalen = global_total.datalen; } op_val.mvtype = op_pars.mvtype = MV_STR; op_val.str.addr = (char *)outfilename;; op_val.str.len = filename_len; op_pars.str.len = sizeof(no_param); op_pars.str.addr = (char *)&no_param; op_close(&op_val, &op_pars); REVERT; if (mu_ctrly_occurred) { gtm_putmsg(VARLSTCNT(1) ERR_EXTRACTCTRLY); mupip_exit(ERR_MUNOFINISH); } gtm_putmsg(VARLSTCNT(8) ERR_RECORDSTAT, 6, LEN_AND_LIT(gt_lit), grand_total.recknt, grand_total.keylen, grand_total.datalen, grand_total.reclen); if (MU_FMT_BINARY == format) { /* truncate the last newline charactor flushed by op_close */ STAT_FILE((char *)outfilename, &statbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(1) errno); TRUNCATE_FILE((const char *)outfilename, statbuf.st_size - 1, truncate_res); if (-1 == truncate_res) rts_error(VARLSTCNT(1) errno); } mupip_exit(success ? SS_NORMAL : ERR_MUNOFINISH); }
void op_zrupdate(int argcnt, ...) { mval *objfilespec; va_list var; mval objpath; char tranbuf[MAX_FBUFF + 1], *chptr, chr; open_relinkctl_sgm *linkctl; relinkrec_t *rec; plength plen; int status, fextlen, fnamlen, fcnt; parse_blk pblk; struct stat outbuf; int stat_res; boolean_t seenfext, fileexists; mstr objdir, rtnname; uint4 hash, prev_hash_index; /* Currently only expecting one value per invocation right now. That will change in phase 2 hence the stdarg setup */ va_start(var, argcnt); assert(1 == argcnt); objfilespec = va_arg(var, mval *); va_end(var); MV_FORCE_STR(objfilespec); /* First some pre-processing to determine if an explicit file name or type was specified. If so, it must be ".o" for * this phase of implementation. Later phases may allow ".m" to be specified but not initially. Use parse_file() to * parse everything out and isolate any extention. */ memset(&pblk, 0, SIZEOF(pblk)); pblk.buffer = tranbuf; pblk.buff_size = (unsigned char)(MAX_FBUFF); /* Pass size of buffer - 1 (standard protocol for parse_file) */ pblk.def1_buf = DOTOBJEXT; /* Default .o file type if not specified */ pblk.def1_size = SIZEOF(DOTOBJEXT) - 1; pblk.fop = F_SYNTAXO; /* Syntax check only - bypass directory existence check */ status = parse_file(&objfilespec->str, &pblk); if (ERR_PARNORMAL != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, status); tranbuf[pblk.b_esl] = '\0'; /* Needed for subsequent STAT_FILE */ seenfext = FALSE; if (0 != pblk.b_ext) { /* If a file extension was specified - get the extension sans any potential wildcard character */ for (chptr = pblk.l_ext + 1, fextlen = pblk.b_ext - 1; 0 < fextlen; chptr++, fextlen--) { /* Check each character in the extension except first which is the dot if ext exists at all */ if (WILDCARD != *chptr) { /* We see a char that isn't a wildcard character. If we've already seen our "o" file extension, * this char makes our requirement filetype impossible so raise an error. */ if (seenfext || (OBJEXT != *chptr)) /* No return from this error */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, ERR_TEXT, 2, RTS_ERROR_TEXT("Unsupported filetype specified")); seenfext = TRUE; } } } /* Do a simlar check for the file type */ if (0 != pblk.b_name) { /* A file name was specified (if not, tiz probably hard to find the file but that can be dealt with later). * Like in the above, the name must be comprised of valid chars for routine names. */ for (chptr = pblk.l_name, fnamlen = pblk.b_name; 0 < fnamlen; chptr++, fnamlen--) { if (WILDCARD != *chptr) { /* Substitute '%' for '_'. While this substitution is really only valid on the first char, only the * first char check allows "%" so a 2nd or later char check would fail the '%' substitution anyway. */ chr = ('_' == *chptr) ? '%' : *chptr; /* We see a char that isn't a wildcard character. If this is the first character, it can be * alpha or percent. If the second or later character, it can be alphanumeric. */ if (((fnamlen != pblk.b_name) && !VALID_MNAME_NFCHAR(chr)) /* 2nd char or later check */ || ((fnamlen == pblk.b_name) && !VALID_MNAME_FCHAR(chr))) /* 1st char check */ { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, ERR_TEXT, 2, RTS_ERROR_TEXT("Filename is not a valid routine name")); } } } } /* When specifying a non-wildcarded object file, it is possible for the file to have been removed, in which case we still * need to update its relinkctl entry (if exists) to notify other processes about the object's deletion. */ if (!(pblk.fnb & F_WILD) & seenfext) { /* If no wildcards in path and saw the extension we want - no need to wash through zsearch() */ objdir.addr = pblk.l_dir; objdir.len = pblk.b_dir; linkctl = relinkctl_attach(&objdir); /* Create/attach/open relinkctl file */ if (NULL == linkctl) /* Non-existant path and no associated relinkctl file */ /* Note this reference to errno depends on nothing in relinkctl_attach() doing anything to modify * errno after the realpath() call. No return from this error. */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, errno); /* What we do at this point depends on the following conditions: * * 1) If the specified file exists, we can add it to relinkctl file and/or update its cycle. * 2) If the file doesn't exist on disk but the routine is found in the relinkctl file, update cycle. * 3) If no file and no entry, just ignore it and do nothing (info error removed by request). */ STAT_FILE(tranbuf, &outbuf, stat_res); if (-1 == stat_res) { if (ENOENT != errno) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, errno); fileexists = FALSE; } else fileexists = TRUE; rtnname.len = pblk.b_name; rtnname.addr = pblk.l_name; CONVERT_FILENAME_TO_RTNNAME(rtnname); /* Set rtnname right before searching in relinkctl file */ assert(valid_mname(&rtnname)); COMPUTE_RELINKCTL_HASH(&rtnname, hash); rec = relinkctl_find_record(linkctl, &rtnname, hash, &prev_hash_index); if ((NULL == rec) && !fileexists) return; /* No file and no entry - ignore */ /* Either the file exists or the entry exists so add or update it */ rec = relinkctl_insert_record(linkctl, &rtnname); RELINKCTL_CYCLE_INCR(rec, linkctl); /* Increment cycle indicating change to world */ return; } /* If we have a wildcarded request or one without the object filetype, reprocess the string with $ZSEARCH using our * defined stream to resolve wildcards. Then loop through processing each file returned. In this loop, we just ignore * any file that doesn't have a ".o" extension. */ op_fnzsearch((mval *)&literal_null, STRM_ZRUPDATE, 0, &objpath); /* Clear any existing cache */ for (fcnt = 0; ; fcnt++) { plen.p.pint = op_fnzsearch(objfilespec, STRM_ZRUPDATE, 0, &objpath); if (0 == objpath.str.len) { /* End of file list */ if (0 == fcnt) /* Still looking to process our first file - give no objects found message as a "soft" message * (INFO level message - supressed in other than direct mode) */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_INFO(ERR_FILEPARSE), 2, objfilespec->str.len, objfilespec->str.addr, ERR_TEXT, 2, RTS_ERROR_TEXT("No object files found")); break; } /* The extension contains the extension-start character ('.') so we are looking for the extension '.o' hence * the length must be 2 and the 2nd char must be OBJEXT. */ if ((2 == plen.p.pblk.b_ext) && (OBJEXT == *(objpath.str.addr + plen.p.pblk.b_dir + plen.p.pblk.b_name + 1))) { /* This is (probably) an object file. Double check file is a file and not a directory */ memcpy(tranbuf, objpath.str.addr, objpath.str.len); /* Need null terminated version for STAT */ tranbuf[objpath.str.len] = '\0'; /* Not guaranteed null termination from op_fnzsearch */ STAT_FILE(tranbuf, &outbuf, stat_res); /* If either something happened to the file since op_fnzsearch() saw it or the file is not a file, then * ignore it. */ if ((-1 == stat_res) || !S_ISREG(outbuf.st_mode)) { fcnt--; /* Don't count files not found for whatever reason */ continue; } /* Before opening the relinkctl file, verify we actually do have a valid routine name */ rtnname.len = plen.p.pblk.b_name; rtnname.addr = objpath.str.addr + plen.p.pblk.b_dir; CONVERT_FILENAME_TO_RTNNAME(rtnname); /* Set rtnname right before searching in relinkctl file */ if (!valid_mname(&rtnname)) { fcnt--; continue; /* Ignore files that are invalid wildcard matches */ } objdir.addr = objpath.str.addr; objdir.len = plen.p.pblk.b_dir; linkctl = relinkctl_attach(&objdir); /* Create/attach/open relinkctl file */ if (NULL == linkctl) { fcnt--; /* Path disappeared - don't count it */ continue; } rec = relinkctl_insert_record(linkctl, &rtnname); RELINKCTL_CYCLE_INCR(rec, linkctl); /* Increment cycle indicating change to world */ } else fcnt--; /* Don't count ignored files */ } }
void mutex_sock_init(void) { mstr mutex_sock_dir_lognam, mutex_sock_dir_transnam; int mutex_sock_path_len; uint4 mutex_sock_trans_status; char mutex_sock_path[MAX_TRANS_NAME_LEN]; int mutex_sock_len, save_errno; struct stat mutex_sock_stat_buf; int status; unsigned char pid_str[2 * sizeof(pid_t) + 1]; error_def(ERR_MUTEXERR); error_def(ERR_TEXT); error_def(ERR_MUTEXRSRCCLNUP); if (mutex_sock_fd != -1) /* Initialization done already */ return; /* Create the socket used for sending and receiving mutex wake mesgs */ if ((mutex_sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) rts_error(VARLSTCNT(7) ERR_MUTEXERR, 0, ERR_TEXT, 2, RTS_ERROR_TEXT("Error with mutex socket create"), errno); memset((char *)&mutex_sock_address, 0, sizeof(mutex_sock_address)); /* Get the socket path */ mutex_sock_dir_lognam.len = sizeof(MUTEX_SOCK_DIR) - 1; mutex_sock_dir_lognam.addr = MUTEX_SOCK_DIR; mutex_sock_trans_status = trans_log_name(&mutex_sock_dir_lognam, &mutex_sock_dir_transnam, mutex_sock_path); if (mutex_sock_trans_status != SS_NORMAL) { strcpy(mutex_sock_path, DEFAULT_MUTEX_SOCK_DIR); mutex_sock_path_len = sizeof(DEFAULT_MUTEX_SOCK_DIR) - 1; } else mutex_sock_path_len = mutex_sock_dir_transnam.len; /* If the path doesn't already end with a '/' pad a '/' */ if (mutex_sock_path[mutex_sock_path_len - 1] != '/') { mutex_sock_path[mutex_sock_path_len++] = '/'; mutex_sock_path[mutex_sock_path_len] = '\0'; } strcpy(mutex_sock_path + mutex_sock_path_len, MUTEX_SOCK_FILE_PREFIX); mutex_sock_path_len += (sizeof(MUTEX_SOCK_FILE_PREFIX) - 1); mutex_wake_this_proc_prefix_len = mutex_sock_path_len; /* Extend mutex_sock_path with pid */ strcpy(mutex_sock_path + mutex_sock_path_len, (char *)pid2ascx(pid_str, process_id)); mutex_sock_path_len += strlen(pid_str); if (mutex_sock_path_len > sizeof(mutex_sock_address.sun_path)) rts_error(VARLSTCNT(6) ERR_MUTEXERR, 0, ERR_TEXT, 2, RTS_ERROR_TEXT("Mutex socket path too long")); mutex_sock_address.sun_family = AF_UNIX; strcpy(mutex_sock_address.sun_path, mutex_sock_path); mutex_sock_len = sizeof(mutex_sock_address.sun_family) + mutex_sock_path_len + 1; /* Include NULL byte in length */ if (UNLINK(mutex_sock_address.sun_path) == -1) /* in case it was left from last time */ { if (errno != ENOENT) { if ((status = send_mesg2gtmsecshr(REMOVE_FILE, (unsigned int)-1, mutex_sock_address.sun_path, mutex_sock_path_len + 1)) == 0) send_msg(VARLSTCNT(8) ERR_MUTEXRSRCCLNUP, 2, mutex_sock_path_len, mutex_sock_path, ERR_TEXT, 2, LEN_AND_LIT("Resource removed by gtmsecshr")); else if (status != ENOENT) /* don't bother if somebody removed the file before gtmsecshr got to it */ rts_error(VARLSTCNT(11) ERR_MUTEXERR, 0, ERR_TEXT, 2, LEN_AND_LIT("gtmsecshr failed to remove leftover mutex resource"), ERR_TEXT, 2, mutex_sock_path_len, mutex_sock_path, status); } } else /* unlink succeeded */ send_msg(VARLSTCNT(4) ERR_MUTEXRSRCCLNUP, 2, mutex_sock_path_len, mutex_sock_path); if (BIND(mutex_sock_fd, (struct sockaddr *)&mutex_sock_address, mutex_sock_len) < 0) rts_error(VARLSTCNT(7) ERR_MUTEXERR, 0, ERR_TEXT, 2, RTS_ERROR_TEXT("Error with mutex socket bind"), errno); /* * Set the socket permissions to override any umask settings. * Allow owner and group read and write access. */ STAT_FILE(mutex_sock_address.sun_path, &mutex_sock_stat_buf, status); if (-1 == status) rts_error(VARLSTCNT(7) ERR_MUTEXERR, 0, ERR_TEXT, 2, RTS_ERROR_TEXT("Error with mutex socket stat"), errno); mutex_sock_stat_buf.st_mode |= (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (-1 == CHMOD(mutex_sock_address.sun_path, mutex_sock_stat_buf.st_mode)) rts_error(VARLSTCNT(7) ERR_MUTEXERR, 0, ERR_TEXT, 2, RTS_ERROR_TEXT("Error with mutex socket chmod"), errno); /* Clear the descriptor set used to sense wake up message */ FD_ZERO(&mutex_wait_on_descs); /* * To make mutex_wake_proc faster, pre-initialize portions of * mutex_wake_this_proc which are invariant of the pid to be woken up. */ memset((char *)&mutex_wake_this_proc, 0, sizeof(mutex_wake_this_proc)); mutex_wake_this_proc.sun_family = AF_UNIX; strcpy(mutex_wake_this_proc.sun_path, mutex_sock_path); mutex_wake_this_proc_len = mutex_sock_len; }