1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
/****************************************************************
* *
* Copyright (c) 2013-2021 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* 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 <sys/types.h>
#include "gtm_stat.h"
#include "gtm_stdlib.h"
#include "gtm_string.h"
#include "gtm_limits.h"
#include "cmd_qlf.h"
#include "gtmio.h"
#include "parse_file.h"
#include <rtnhdr.h>
#include "obj_file.h"
GBLREF command_qualifier cmd_qlf;
GBLREF char object_file_name[];
GBLREF short object_name_len;
GBLREF mident module_name;
#define MKSTEMP_MASK "XXXXXX"
#define MAX_MKSTEMP_RETRIES 100
error_def(ERR_FILEPARSE);
error_def(ERR_OBJFILERR);
error_def(ERR_SYSCALL);
error_def(ERR_TEXT);
/********************************************************************************************************************************
*
* While these routines might rightly belong in obj_file.c, since these routines are needed both in sr_unix and in sr_unix_nsb,
* it was decided to create this module to share routines that are the same across both unix and linux-i386 so the routines only
* need to exist in one place.
*
********************************************************************************************************************************/
/**
* @brief Try to memcpy to tmp_object_file_name in a way which SCA will be happy with
*
* @param src Source buffer
* @param cpy_len Number of bytes to copy
*
* @return None
*/
static inline void mcpy_tmp_object_file_name(const char *src, size_t cpy_len)
{
typedef char dst_buf[TLEN(tmp_object_file_name)];
typedef dst_buf *dst_buf_p;
dst_buf_p tmp_object_file_name;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
tmp_object_file_name = (dst_buf_p) TADR(tmp_object_file_name);
assert(NULL != src);
assert(tmp_object_file_name != NULL);
assert(sizeof(*tmp_object_file_name) >= cpy_len);
memcpy((char *)tmp_object_file_name, src, cpy_len);
assert(NULL != tmp_object_file_name);
assert((sizeof(*tmp_object_file_name) - cpy_len) >= SIZEOF(MKSTEMP_MASK));
memcpy(((char *)tmp_object_file_name) + cpy_len, MKSTEMP_MASK, SIZEOF(MKSTEMP_MASK));
}
/* Routine to create a temporary object file. This file is created in the directory it is supposed to reside in but is created
* with a temporary name. When complete, it is renamed to what it was meant to be replacing the previous version.
*
* Parameters:
*
* object_fname - Character array of the object path/name.
* object_fname_len - Length of that array in bytes.
*
* Return value:
* File descriptor for the open object file.
*/
int mk_tmp_object_file(const char *object_fname, int object_fname_len)
{
int fdesc, status, umask_creat, umask_orig, retry;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
/* Make sure room in buffer for addition of unique-ifying MKSTEMP_MASK on end of file name */
if ((object_fname_len + SIZEOF(MKSTEMP_MASK) - 1) > TLEN(tmp_object_file_name))
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(9) ERR_OBJFILERR, 2, object_fname_len, object_fname, ERR_TEXT,
2, RTS_ERROR_TEXT("Object file name exceeds buffer size"));
/* The mkstemp() routine is known to bogus-fail for no apparent reason at all especially on AIX 6.1. In the event
* this shortcoming plagues other platforms as well, we add a low-cost retry wrapper.
*/
retry = MAX_MKSTEMP_RETRIES;
do
{
/*memcpy(TADR(tmp_object_file_name), object_fname, object_fname_len);*/
mcpy_tmp_object_file_name(object_fname, object_fname_len);
/* Note memcpy() below purposely includes null terminator */
/*memcpy(TADR(tmp_object_file_name) + object_fname_len, MKSTEMP_MASK, SIZEOF(MKSTEMP_MASK));*/
MKSTEMP(TADR(tmp_object_file_name), fdesc);
} while ((FD_INVALID == fdesc) && (EEXIST == errno) && (0 < --retry));
if (FD_INVALID == fdesc)
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(5) ERR_OBJFILERR, 2, object_fname_len, object_fname, errno);
umask_orig = umask(000); /* Determine umask (destructive) */
(void)umask(umask_orig); /* Reset umask */
umask_creat = 0666 & ~umask_orig;
/* Change protections to be those generated by previous versions. In some future version, the permissions may
* become tied to the permissions of the source but this works for now.
*/
status = FCHMOD(fdesc, umask_creat);
if (-1 == status)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("fchmod()"), CALLFROM, errno);
return fdesc;
}
/* Routine to rename the most recent temporary object file (name stored in threadgbl tmp_object_file_name) to the name
* passed in via parameter.
*
* Parameters:
* object_fname - non-temporary name of object file
*
* Global input:
* tmp_object_file_name - private/unique file created by mkstemp() in routine above.
*/
void rename_tmp_object_file(const char *object_fname)
{
int status;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
status = rename(TADR(tmp_object_file_name), object_fname);
if (-1 == status)
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("rename()"), CALLFROM, errno);
memset(TADR(tmp_object_file_name), 0, GTM_PATH_MAX);
}
/* Routine to determine and initialize the fully qualified object name and path.
*
* Parameters:
* - none
*
* Global inputs:
* cmd_qlf.object_file - value from -object= option
* module_name - routine name
* Global outputs:
* object_file_name - full path of object file
* object_name_len - length of full path (not including null terminator)
*/
void init_object_file_name(void)
{
int status, rout_len;
char obj_name[SIZEOF(mident_fixed) + 5];
mstr fstr;
parse_blk pblk;
fstr.len = (MV_DEFINED(&cmd_qlf.object_file) && (MAX_FN_LEN > cmd_qlf.object_file.str.len)
? cmd_qlf.object_file.str.len : 0);
fstr.addr = cmd_qlf.object_file.str.addr;
assert(!fstr.len || strlen(fstr.addr) == fstr.len);
memset(&pblk, 0, SIZEOF(pblk));
pblk.buffer = object_file_name;
pblk.buff_size = MAX_FN_LEN;
rout_len = (int)module_name.len;
memcpy(&obj_name[0], module_name.addr, rout_len);
memcpy(&obj_name[rout_len], DOTOBJ, SIZEOF(DOTOBJ)); /* Includes null terminator */
pblk.def1_size = rout_len + SIZEOF(DOTOBJ) - 1; /* Length does not include null terminator */
pblk.def1_buf = obj_name;
status = parse_file(&fstr, &pblk);
if (0 == (status & 1))
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status);
object_name_len = pblk.b_esl;
object_file_name[object_name_len] = '\0';
}
|