File: obj_fileu.c

package info (click to toggle)
fis-gtm 7.1-006-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,908 kB
  • sloc: ansic: 344,906; asm: 5,184; csh: 4,859; sh: 2,000; awk: 294; makefile: 73; sed: 13
file content (183 lines) | stat: -rw-r--r-- 6,779 bytes parent folder | download | duplicates (3)
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';
}