예제 #1
0
void mupip_rctldump(void)
{
#	ifdef AUTORELINK_SUPPORTED
	unsigned short		max_len;
	mstr			dir;
	char			objdir[GTM_PATH_MAX];
	open_relinkctl_sgm	*linkctl;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	if (TREF(parms_cnt))
	{
		assert(1 == TREF(parms_cnt));
		max_len = SIZEOF(objdir);
		if (!cli_get_str("DIRECTORY", objdir, &max_len))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_MUPCLIERR);
		dir.addr = objdir;
		dir.len = max_len;
		linkctl = relinkctl_attach(&dir);
		assert(linkctl == TREF(open_relinkctl_list));
		assert((NULL == linkctl) || (NULL == linkctl->next));
	} else
		zro_init();
	util_out_print("", RESET);	/* Reset output buffer */
	zshow_rctldump(NULL);		/* callee knows caller is mupip_rctldump type based on the NULL parameter */
#	endif	/* AUTORELINK_SUPPORTED */
}
예제 #2
0
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 */

	}
}
예제 #3
0
파일: zro_load.c 프로젝트: mihawk/fis-gtm
/* 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 */
}