372 lines
12 KiB
C
372 lines
12 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include "gtm_fcntl.h"
|
|
#include "gtm_stat.h"
|
|
#include "gtm_string.h"
|
|
#include "gtm_unistd.h"
|
|
#include <errno.h>
|
|
|
|
#include "stringpool.h"
|
|
#include "zroutines.h"
|
|
#include "cmd_qlf.h"
|
|
#include "parse_file.h"
|
|
#include "gtmio.h"
|
|
#include "eintr_wrappers.h"
|
|
#include "op.h"
|
|
#include "incr_link.h"
|
|
#include "compiler.h"
|
|
#ifdef __MVS__
|
|
#include "gtm_zos_io.h"
|
|
#endif
|
|
|
|
#define SRC 1
|
|
#define OBJ 2
|
|
#define NOTYPE 3
|
|
|
|
GBLREF spdesc stringpool;
|
|
GBLREF command_qualifier glb_cmd_qlf, cmd_qlf;
|
|
GBLREF mval dollar_zsource;
|
|
GBLREF int object_file_des;
|
|
|
|
error_def(ERR_WILDCARD);
|
|
error_def(ERR_VERSION);
|
|
error_def(ERR_FILENOTFND);
|
|
error_def(ERR_ZLINKFILE);
|
|
error_def(ERR_ZLNOOBJECT);
|
|
error_def(ERR_FILEPARSE);
|
|
error_def(ERR_TEXT);
|
|
ZOS_ONLY(error_def(ERR_BADTAG);)
|
|
|
|
void op_zlink (mval *v, mval *quals)
|
|
{
|
|
int status, qlf, tslash;
|
|
unsigned short type;
|
|
char srcnamebuf[MAX_FBUFF + 1], objnamebuf[MAX_FBUFF + 1], *fname;
|
|
uint4 objnamelen, srcnamelen;
|
|
char inputf[MAX_FBUFF + 1], obj_file[MAX_FBUFF + 1], list_file[MAX_FBUFF + 1],
|
|
ceprep_file[MAX_FBUFF + 1];
|
|
zro_ent *srcdir, *objdir;
|
|
mstr srcstr, objstr, file;
|
|
boolean_t compile, expdir, obj_found, src_found;
|
|
parse_blk pblk;
|
|
mval qualifier;
|
|
struct stat obj_stat, src_stat;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
MV_FORCE_STR(v);
|
|
if (!v->str.len || (MAX_FBUFF < v->str.len))
|
|
rts_error(VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
|
|
object_file_des = FD_INVALID;
|
|
srcdir = objdir = (zro_ent *) 0;
|
|
expdir = FALSE;
|
|
if (quals)
|
|
{ /* explicit ZLINK */
|
|
memset(&pblk, 0, SIZEOF(pblk));
|
|
pblk.buff_size = MAX_FBUFF;
|
|
pblk.buffer = inputf;
|
|
pblk.fop = F_SYNTAXO;
|
|
status = parse_file(&v->str, &pblk);
|
|
if (!(status & 1))
|
|
rts_error(VARLSTCNT(5) ERR_FILEPARSE, 2, v->str.len, v->str.addr, status);
|
|
if (pblk.fnb & F_WILD)
|
|
rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
|
|
ERR_WILDCARD, 2, v->str.len, v->str.addr);
|
|
file.addr = pblk.buffer;
|
|
file.len = pblk.b_esl;
|
|
type = NOTYPE;
|
|
expdir = 0 != (pblk.fnb & F_HAS_DIR);
|
|
if (pblk.b_ext)
|
|
{
|
|
file.len -= pblk.b_ext;
|
|
if (('o' == pblk.l_ext[1]) && (2 == pblk.b_ext))
|
|
type = OBJ;
|
|
else
|
|
type = SRC;
|
|
}
|
|
if (!expdir)
|
|
{
|
|
file.addr = pblk.l_name;
|
|
file.len = pblk.b_name;
|
|
}
|
|
ENSURE_STP_FREE_SPACE(file.len);
|
|
memcpy(stringpool.free, file.addr, file.len);
|
|
dollar_zsource.str.addr = (char *) stringpool.free;
|
|
dollar_zsource.str.len = file.len;
|
|
stringpool.free += file.len;
|
|
if (OBJ == type)
|
|
{
|
|
memmove(objnamebuf,file.addr, file.len + pblk.b_ext);
|
|
objnamelen = file.len + pblk.b_ext;
|
|
assert (objnamelen <= MAX_FBUFF + 1);
|
|
objnamebuf[objnamelen] = 0;
|
|
} else if (SRC == type)
|
|
{
|
|
memmove(srcnamebuf, file.addr,file.len + pblk.b_ext);
|
|
srcnamelen = file.len + pblk.b_ext;
|
|
assert (srcnamelen <= MAX_FBUFF + 1);
|
|
srcnamebuf[srcnamelen] = 0;
|
|
objnamelen = file.len;
|
|
if (pblk.b_name > MAX_MIDENT_LEN)
|
|
objnamelen = expdir ? (pblk.b_dir + MAX_MIDENT_LEN) : MAX_MIDENT_LEN;
|
|
memcpy(objnamebuf, file.addr, objnamelen);
|
|
memcpy(&objnamebuf[objnamelen], DOTOBJ, SIZEOF(DOTOBJ));
|
|
objnamelen += STR_LIT_LEN(DOTOBJ);
|
|
assert (objnamelen + SIZEOF(DOTOBJ) <= MAX_FBUFF + 1);
|
|
} else
|
|
{
|
|
if (file.len + SIZEOF(DOTM) > SIZEOF(srcnamebuf) ||
|
|
file.len + SIZEOF(DOTOBJ) > SIZEOF(objnamebuf))
|
|
rts_error(VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
|
|
memmove(srcnamebuf, file.addr, file.len);
|
|
memcpy(&srcnamebuf[file.len], DOTM, SIZEOF(DOTM));
|
|
srcnamelen = file.len + SIZEOF(DOTM) - 1;
|
|
assert (srcnamelen + SIZEOF(DOTM) <= MAX_FBUFF + 1);
|
|
memcpy(objnamebuf,file.addr,file.len);
|
|
memcpy(&objnamebuf[file.len], DOTOBJ, SIZEOF(DOTOBJ));
|
|
objnamelen = file.len + SIZEOF(DOTOBJ) - 1;
|
|
assert (objnamelen + SIZEOF(DOTOBJ) <= MAX_FBUFF + 1);
|
|
}
|
|
if (!expdir)
|
|
{
|
|
srcstr.addr = srcnamebuf;
|
|
srcstr.len = srcnamelen;
|
|
objstr.addr = objnamebuf;
|
|
objstr.len = objnamelen;
|
|
if (OBJ == type)
|
|
{
|
|
zro_search(&objstr, &objdir, 0, 0, TRUE);
|
|
if (!objdir)
|
|
rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
|
|
ERR_FILENOTFND, 2, dollar_zsource.str.len, dollar_zsource.str.addr);
|
|
} else if (SRC == type)
|
|
{
|
|
zro_search(&objstr, &objdir, &srcstr, &srcdir, TRUE);
|
|
if (!srcdir)
|
|
rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf,
|
|
ERR_FILENOTFND, 2, srcnamelen, srcnamebuf);
|
|
} else
|
|
{
|
|
zro_search(&objstr, &objdir, &srcstr, &srcdir, NON_USHBIN_ONLY(TRUE) USHBIN_ONLY(FALSE));
|
|
if (!objdir && !srcdir)
|
|
rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
|
|
ERR_FILENOTFND, 2, dollar_zsource.str.len, dollar_zsource.str.addr);
|
|
}
|
|
}
|
|
} else
|
|
{ /* auto-ZLINK */
|
|
type = NOTYPE;
|
|
memcpy(srcnamebuf,v->str.addr,v->str.len);
|
|
memcpy(&srcnamebuf[v->str.len], DOTM, SIZEOF(DOTM));
|
|
srcnamelen = v->str.len + SIZEOF(DOTM) - 1;
|
|
if ('%' == srcnamebuf[0])
|
|
srcnamebuf[0] = '_';
|
|
memcpy(objnamebuf, srcnamebuf, v->str.len);
|
|
memcpy(&objnamebuf[v->str.len], DOTOBJ, SIZEOF(DOTOBJ));
|
|
objnamelen = v->str.len + SIZEOF(DOTOBJ) - 1;
|
|
srcstr.addr = srcnamebuf;
|
|
srcstr.len = srcnamelen;
|
|
objstr.addr = objnamebuf;
|
|
objstr.len = objnamelen;
|
|
/* On shared platforms, skip parameter should be FALSE to indicate an auto-ZLINK so that
|
|
* zro_search looks into shared libraries. On non-shared platforms, it should be
|
|
* TRUE to instruct zro_search to always skip shared libraries
|
|
*/
|
|
zro_search(&objstr, &objdir, &srcstr, &srcdir, NON_USHBIN_ONLY(TRUE) USHBIN_ONLY(FALSE));
|
|
if (!objdir && !srcdir)
|
|
rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
|
|
ERR_FILENOTFND, 2, v->str.len, v->str.addr);
|
|
qualifier.mvtype = MV_STR;
|
|
qualifier.str = TREF(dollar_zcompile);
|
|
quals = &qualifier;
|
|
}
|
|
if (OBJ == type)
|
|
{
|
|
if (objdir)
|
|
{
|
|
assert(ZRO_TYPE_OBJLIB != objdir->type);
|
|
if (objdir->str.len + objnamelen + 2 > SIZEOF(objnamebuf))
|
|
rts_error(VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
|
|
if (objdir->str.len)
|
|
{
|
|
tslash = ('/' == objdir->str.addr[objdir->str.len - 1]) ? 0 : 1;
|
|
memmove(&objnamebuf[ objdir->str.len + tslash], objnamebuf, objnamelen);
|
|
if (tslash)
|
|
objnamebuf[ objdir->str.len ] = '/';
|
|
memcpy(objnamebuf, objdir->str.addr, objdir->str.len);
|
|
objnamelen += objdir->str.len + tslash;
|
|
objnamebuf[ objnamelen ] = 0;
|
|
}
|
|
}
|
|
OPEN_OBJECT_FILE(objnamebuf, O_RDONLY, object_file_des);
|
|
if (FD_INVALID == object_file_des)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, errno);
|
|
if (USHBIN_ONLY(!incr_link(object_file_des, NULL)) NON_USHBIN_ONLY(!incr_link(object_file_des)))
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, ERR_VERSION);
|
|
CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, errno);
|
|
} else /* either NO type or SOURCE type */
|
|
{
|
|
cmd_qlf.object_file.str.addr = obj_file;
|
|
cmd_qlf.object_file.str.len = MAX_FBUFF;
|
|
cmd_qlf.list_file.str.addr = list_file;
|
|
cmd_qlf.list_file.str.len = MAX_FBUFF;
|
|
cmd_qlf.ceprep_file.str.addr = ceprep_file;
|
|
cmd_qlf.ceprep_file.str.len = MAX_FBUFF;
|
|
if (srcdir)
|
|
{
|
|
assert(ZRO_TYPE_OBJLIB != objdir->type);
|
|
if (srcdir->str.len + srcnamelen > SIZEOF(srcnamebuf) - 1)
|
|
rts_error(VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
|
|
if (srcdir->str.len)
|
|
{
|
|
tslash = ('/' == srcdir->str.addr[srcdir->str.len - 1]) ? 0 : 1;
|
|
memmove(&srcnamebuf[ srcdir->str.len + tslash ], srcnamebuf, srcnamelen);
|
|
if (tslash)
|
|
srcnamebuf[ srcdir->str.len ] = '/';
|
|
memcpy(srcnamebuf, srcdir->str.addr, srcdir->str.len);
|
|
srcnamelen += srcdir->str.len + tslash;
|
|
srcnamebuf[ srcnamelen ] = 0;
|
|
}
|
|
}
|
|
if (objdir)
|
|
{
|
|
if (ZRO_TYPE_OBJLIB == objdir->type)
|
|
{
|
|
NON_USHBIN_ONLY(GTMASSERT;)
|
|
assert(objdir->shrlib);
|
|
assert(objdir->shrsym);
|
|
USHBIN_ONLY(
|
|
if (!incr_link(0, objdir))
|
|
GTMASSERT;
|
|
)
|
|
return;
|
|
}
|
|
if (objdir->str.len + objnamelen > SIZEOF(objnamebuf) - 1)
|
|
rts_error(VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
|
|
if (objdir->str.len)
|
|
{
|
|
tslash = ('/' == objdir->str.addr[objdir->str.len - 1]) ? 0 : 1;
|
|
memmove(&objnamebuf[ objdir->str.len + tslash ], objnamebuf, objnamelen);
|
|
if (tslash)
|
|
objnamebuf[ objdir->str.len ] = '/';
|
|
memcpy(objnamebuf, objdir->str.addr, objdir->str.len);
|
|
objnamelen += objdir->str.len + tslash;
|
|
objnamebuf[ objnamelen ] = 0;
|
|
}
|
|
}
|
|
src_found = obj_found = compile = FALSE;
|
|
if (SRC != type)
|
|
{
|
|
OPEN_OBJECT_FILE(objnamebuf, O_RDONLY, object_file_des);
|
|
if (FD_INVALID == object_file_des)
|
|
{
|
|
if (ENOENT == errno)
|
|
obj_found = FALSE;
|
|
else
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
} else
|
|
obj_found = TRUE;
|
|
} else
|
|
compile = TRUE;
|
|
STAT_FILE(srcnamebuf, &src_stat, status);
|
|
if (-1 == status)
|
|
{
|
|
if ((ENOENT == errno) && (SRC != type))
|
|
src_found = FALSE;
|
|
else
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE,2,srcnamelen,srcnamebuf,errno);
|
|
} else
|
|
src_found = TRUE;
|
|
if (SRC != type)
|
|
{
|
|
if (src_found)
|
|
{
|
|
if (obj_found)
|
|
{
|
|
FSTAT_FILE(object_file_des, &obj_stat, status);
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
if (src_stat.st_mtime > obj_stat.st_mtime)
|
|
{
|
|
CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des"
|
|
* to FD_INVALID */
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
compile = TRUE;
|
|
}
|
|
} else
|
|
compile = TRUE;
|
|
} else if (!obj_found)
|
|
rts_error (VARLSTCNT(8) ERR_ZLINKFILE, 2, objnamelen, objnamebuf,
|
|
ERR_FILENOTFND, 2, objnamelen, objnamebuf);
|
|
}
|
|
if (compile)
|
|
{
|
|
zl_cmd_qlf(&quals->str, &cmd_qlf);
|
|
if (!MV_DEFINED(&cmd_qlf.object_file))
|
|
{
|
|
cmd_qlf.object_file.mvtype = MV_STR;
|
|
cmd_qlf.object_file.str.addr = objnamebuf;
|
|
cmd_qlf.object_file.str.len = objnamelen;
|
|
}
|
|
qlf = cmd_qlf.qlf;
|
|
if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type))
|
|
{
|
|
cmd_qlf.qlf = glb_cmd_qlf.qlf;
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
|
|
}
|
|
zlcompile(srcnamelen, (uchar_ptr_t)srcnamebuf);
|
|
if ((SRC == type) && !(qlf & CQ_OBJECT))
|
|
return;
|
|
}
|
|
CONVERT_OBJECT_LOCK(object_file_des, F_RDLCK, status);
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
status = USHBIN_ONLY(incr_link(object_file_des, NULL)) NON_USHBIN_ONLY(incr_link(object_file_des));
|
|
if (!status)
|
|
{ /* due only to version mismatch, so recompile */
|
|
CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
if (compile)
|
|
GTMASSERT;
|
|
if (!src_found)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_VERSION);
|
|
zl_cmd_qlf(&quals->str, &cmd_qlf);
|
|
if (!MV_DEFINED(&cmd_qlf.object_file))
|
|
{
|
|
cmd_qlf.object_file.mvtype = MV_STR;
|
|
cmd_qlf.object_file.str.addr = objnamebuf;
|
|
cmd_qlf.object_file.str.len = objnamelen;
|
|
}
|
|
zlcompile(srcnamelen, (uchar_ptr_t)srcnamebuf);
|
|
if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type))
|
|
{
|
|
cmd_qlf.qlf = glb_cmd_qlf.qlf;
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
|
|
}
|
|
CONVERT_OBJECT_LOCK(object_file_des, F_RDLCK, status);
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
if (USHBIN_ONLY(!incr_link(object_file_des, NULL)) NON_USHBIN_ONLY(!incr_link(object_file_des)))
|
|
GTMASSERT;
|
|
}
|
|
CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
|
|
if (-1 == status)
|
|
rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
|
|
}
|
|
}
|