183 lines
4.6 KiB
C
183 lines
4.6 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2009 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"
|
||
|
|
||
|
#ifdef GTM_FD_TRACE
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
/* Before including gtm_fcntl.h, make sure we do not redefine open/creat/close etc. as this module
|
||
|
* is where we are defining the interlude functions gtm_open/gtm_creat etc. to use the real system version.
|
||
|
* Note that if the system include file redefined open/creat etc. (e.g. HPUX redefines open to __open64 to allow
|
||
|
* for large file support) we want to make sure we use the system redefined versions here. So it is necessary
|
||
|
* to disable any redefining of these functions that GT.M otherwise does.
|
||
|
*/
|
||
|
#undef GTM_FD_TRACE
|
||
|
|
||
|
#include "gtm_fcntl.h"
|
||
|
#include "gtm_stat.h"
|
||
|
#include "gtm_unistd.h"
|
||
|
#include "gtm_socket.h"
|
||
|
#include "caller_id.h"
|
||
|
#include "iosp.h"
|
||
|
#include "error.h"
|
||
|
#include "gtm_string.h"
|
||
|
#include "send_msg.h"
|
||
|
|
||
|
/* This is a GT.M wrapper module for all system calls that open/close file descriptors.
|
||
|
* This is needed to trace all files that were opened by GT.M (D9I11-002714)
|
||
|
*/
|
||
|
|
||
|
enum fd_ops
|
||
|
{
|
||
|
fd_ops_open = 1, /* open */
|
||
|
fd_ops_open3, /* open */
|
||
|
fd_ops_creat, /* creat */
|
||
|
fd_ops_dup, /* dup */
|
||
|
fd_ops_dup2, /* dup2 */
|
||
|
fd_ops_pipe0, /* pipe */
|
||
|
fd_ops_pipe1, /* pipe */
|
||
|
fd_ops_socket, /* socket */
|
||
|
fd_ops_close /* close */
|
||
|
};
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
caddr_t call_from;
|
||
|
int fd;
|
||
|
enum fd_ops fd_act;
|
||
|
int4 status; /* valid only if fd_act is fd_ops_close or fd_ops_pipe{0,1} */
|
||
|
} fd_trace;
|
||
|
|
||
|
#define FD_OPS_ARRAY_SIZE 512
|
||
|
|
||
|
GBLDEF int4 fd_ops_array_index = -1;
|
||
|
GBLDEF int4 fd_ops_array_num_wraps = 0; /* to get an idea how many total files were opened/closed */
|
||
|
GBLDEF fd_trace fd_ops_array[FD_OPS_ARRAY_SIZE]; /* space for FD_TRACE macro to record info */
|
||
|
|
||
|
/* Determine on what platforms and build types we want to get caller_id information. In pro builds, invoke caller_id only on
|
||
|
* those platforms where caller_id is lightweight (i.e. caller_id.s exists). Thankfully AIX (necessary for D9I11-002714)
|
||
|
* falls in this category. For debug builds, invoke caller_id unconditionally since performance is not a big concern.
|
||
|
*/
|
||
|
#if (defined(DEBUG) || defined(_AIX) || defined(__sparc) || defined(__MVS__) || defined(Linux390) \
|
||
|
|| (defined(__linux__) && (defined(__i386))) || defined(__osf__))
|
||
|
# define GET_CALLER_ID caller_id()
|
||
|
#else
|
||
|
# define GET_CALLER_ID 0
|
||
|
#endif
|
||
|
|
||
|
#define FD_TRACE(OPS, FD, STATUS) \
|
||
|
{ \
|
||
|
++fd_ops_array_index; \
|
||
|
if (FD_OPS_ARRAY_SIZE <= fd_ops_array_index) \
|
||
|
{ \
|
||
|
fd_ops_array_num_wraps++; \
|
||
|
fd_ops_array_index = 0; \
|
||
|
} \
|
||
|
fd_ops_array[fd_ops_array_index].call_from = (caddr_t)GET_CALLER_ID; \
|
||
|
fd_ops_array[fd_ops_array_index].fd_act = OPS; \
|
||
|
fd_ops_array[fd_ops_array_index].fd = FD; \
|
||
|
fd_ops_array[fd_ops_array_index].status = (int4)STATUS; \
|
||
|
}
|
||
|
|
||
|
int gtm_open(const char *pathname, int flags)
|
||
|
{
|
||
|
int fd;
|
||
|
|
||
|
fd = open(pathname, flags);
|
||
|
FD_TRACE(fd_ops_open, fd, 0);
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int gtm_open3(const char *pathname, int flags, mode_t mode)
|
||
|
{
|
||
|
int fd;
|
||
|
|
||
|
fd = open(pathname, flags, mode);
|
||
|
FD_TRACE(fd_ops_open3, fd, 0);
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int gtm_creat(const char *pathname, mode_t mode)
|
||
|
{
|
||
|
int fd;
|
||
|
|
||
|
fd = creat(pathname, mode);
|
||
|
FD_TRACE(fd_ops_creat, fd, 0);
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int gtm_dup(int oldfd)
|
||
|
{
|
||
|
int newfd;
|
||
|
|
||
|
newfd = dup(oldfd);
|
||
|
FD_TRACE(fd_ops_dup, newfd, oldfd);
|
||
|
assert(-1 != newfd);
|
||
|
return newfd;
|
||
|
}
|
||
|
|
||
|
int gtm_dup2(int oldfd, int newfd)
|
||
|
{
|
||
|
int status;
|
||
|
|
||
|
status = dup2(oldfd, newfd);
|
||
|
assert((-1 == status) || (newfd == status));
|
||
|
FD_TRACE(fd_ops_dup2, newfd, (-1 == status) ? status : oldfd);
|
||
|
assert(-1 != newfd);
|
||
|
return newfd;
|
||
|
}
|
||
|
|
||
|
int gtm_pipe1(int pipefd[2])
|
||
|
{
|
||
|
int status;
|
||
|
|
||
|
status = pipe(pipefd);
|
||
|
FD_TRACE(fd_ops_pipe0, pipefd[0], status);
|
||
|
FD_TRACE(fd_ops_pipe1, pipefd[1], status);
|
||
|
assert(-1 != status);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
int gtm_socket(int domain, int type, int protocol)
|
||
|
{
|
||
|
int fd;
|
||
|
|
||
|
fd = socket(domain, type, protocol);
|
||
|
FD_TRACE(fd_ops_socket, fd, 0);
|
||
|
assert(-1 != fd);
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int gtm_close(int fd)
|
||
|
{
|
||
|
int status;
|
||
|
int save_errno;
|
||
|
|
||
|
error_def(ERR_CLOSEFAIL);
|
||
|
error_def(ERR_CALLERID);
|
||
|
|
||
|
status = close(fd);
|
||
|
save_errno = errno;
|
||
|
FD_TRACE(fd_ops_close, fd, status);
|
||
|
if ((-1 == status) && (EINTR != save_errno))
|
||
|
{
|
||
|
send_msg(VARLSTCNT(4) ERR_CLOSEFAIL, 1, fd, save_errno);
|
||
|
SEND_CALLERID("gtm_close()");
|
||
|
assert(FALSE);
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
#endif
|