/*
* Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: stthreadsio.c,v 1.25 2006/07/16 02:07:40 ca Exp $")
#include "sm/error.h"
#include "fcntl.h"
#include "sm/memops.h"
#include "sm/stat.h"
#include "sm/time.h"
#include "sm/heap.h"
#include "sm/assert.h"
#include "sm/varargs.h"
#include "sm/io.h"
#include "sm/fdset.h"
#include "sm/stthreads.h"
#include "io-int.h"
#include "statethreads/st.h"
static read_F sm_thrread;
static write_F sm_thrwrite;
#if 0
static sm_ret_T
sm_thrssm_ret_T(sm_file_T *fp, off_t offset, int whence);
#endif
static close_F sm_thrclose;
static sm_ret_T
sm_thrgetmode(sm_file_T *fp, int *mode);
static getinfo_F sm_thrgetinfo;
static setinfo_F sm_thrsetinfo;
static open_F sm_thrfdopen;
static seek_F sm_thrseek;
static open_F sm_thrnetopen;
#if 0
close_F sm_thrnetclose;
#endif
sm_stream_T SmStThrIO =
SM_STREAM_STRUCT(sm_thrfdopen, sm_thrclose, sm_thrread, sm_thrwrite, \
NULL, NULL, sm_thrseek, sm_thrgetinfo, sm_thrsetinfo);
sm_stream_T SmStThrNetIO =
SM_STREAM_STRUCT(sm_thrnetopen, sm_thrclose, sm_thrread, sm_thrwrite, \
NULL, NULL, sm_thrseek, sm_thrgetinfo, sm_thrsetinfo);
#define f_netfd(fp) ((st_netfd_t) f_cookie(fp))
#define assign_f_netfd(fp, netfd) f_cookie(fp) = (void *) (netfd)
/*
** SM_THRREAD -- read from the file
**
** Parameters:
** fp -- file pointer to read from
** buf -- location to place read data
** n -- number of bytes to read
** bytesread -- number of bytes read (output)
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_thrread(sm_file_T *fp, uchar *buf, size_t n, ssize_t *bytesread)
{
ssize_t ret;
do
{
errno = 0;
ret = st_read(f_netfd(*fp), buf, n, SEC2USEC(fp->f_timeout));
} while (ret == -1 && errno == EINTR);
if (ret == -1)
{
int e;
e = errno;
*bytesread = 0;
if (E_IS_TEMP(e))
return sm_error_temp(SM_EM_STTHRIO, e);
return sm_error_perm(SM_EM_STTHRIO, e);
}
*bytesread = ret;
return SM_SUCCESS;
}
/*
** SM_THRWRITE -- write to the file
**
** Parameters:
** fp -- file pointer ro write to
** buf -- location of data to be written
** n -- number of bytes to write
** byteswritten -- number of bytes written (output)
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_thrwrite(sm_file_T *fp, const uchar *buf, size_t n, ssize_t *byteswritten)
{
ssize_t ret;
do
{
errno = 0;
ret = st_write(f_netfd(*fp), buf, n, SEC2USEC(fp->f_timeout));
} while (ret == -1 && errno == EINTR);
if (ret == -1)
{
int e;
e = errno;
*byteswritten = 0;
if (E_IS_TEMP(e))
return sm_error_temp(SM_EM_STTHRIO, e);
return sm_error_perm(SM_EM_STTHRIO, e);
}
*byteswritten = ret;
return SM_SUCCESS;
}
/*
** SM_THRSEEK -- set the file offset position
**
** Parmeters:
** fp -- file pointer to position
** offset -- how far to position from "base" (set by 'whence')
** whence -- indicates where the "base" of the 'offset' to start
**
** Results:
** sm_error_perm(SM_EM_STTHRIO, ESPIPE)
*/
/* ARGSUSED0 */
static sm_ret_T
sm_thrseek(sm_file_T *fp, off_t offset, int whence)
{
return sm_error_perm(SM_EM_STTHRIO, ESPIPE);
}
/*
** SM_THRCLOSE -- close the file
**
** Parameters:
** fp -- the file pointer to close
** flags -- ignored
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_thrclose(sm_file_T *fp, int flags)
{
int r;
r = st_netfd_close(f_netfd(*fp));
if (r == -1)
return sm_error_perm(SM_EM_STTHRIO, errno);
return SM_SUCCESS;
}
/*
** SM_THRSETMODE -- set the access mode for the file
** Called by sm_stdsetinfo().
** XXX do we really want to allow changing the mode?
**
** Parameters:
** fp -- file pointer
** mode -- new mode to set the file access to
**
** Results:
** Success: 0 (zero);
** Failure: -1 and sets errno
*/
static sm_ret_T
sm_thrsetmode(sm_file_T *fp, const int *mode)
{
int flags = 0;
switch (*mode)
{
case SM_IO_RDWR:
flags |= SMRW;
break;
case SM_IO_RDONLY:
flags |= SMRD;
break;
case SM_IO_WRONLY:
flags |= SMWR;
break;
case SM_IO_APPEND:
default:
return sm_error_perm(SM_EM_STTHRIO, EINVAL);
}
f_flags(*fp) = f_flags(*fp) & ~SMMODEMASK;
f_flags(*fp) |= flags;
return SM_SUCCESS;
}
/*
** SM_THRGETMODE -- for getinfo determine open mode
**
** Called by sm_thrgetinfo().
**
** Parameters:
** fp -- the file mode being determined
** mode -- internal mode to map to external value
**
** Results:
** Failure: -1 and sets errno
** Success: external mode value
*/
static sm_ret_T
sm_thrgetmode(sm_file_T *fp, int *mode)
{
switch (f_flags(*fp) & SMMODEMASK)
{
case SMRW:
*mode = SM_IO_RDWR;
break;
case SMRD:
*mode = SM_IO_RDONLY;
break;
case SMWR:
*mode = SM_IO_WRONLY;
break;
default:
return sm_error_perm(SM_EM_STTHRIO, EINVAL);
}
return SM_SUCCESS;
}
/*
** SM_THRSETINFO -- set/modify information for a file
**
** Parameters:
** fp -- file to set info for
** what -- type of info to set
** valp -- location of data used for setting
**
** Returns:
** usual sm_error code.
*/
static sm_ret_T
sm_thrsetinfo(sm_file_T *fp, int what, void *valp)
{
switch (what)
{
case SM_IO_WHAT_MODE:
return sm_thrsetmode(fp, (const int *)valp);
default:
return sm_error_perm(SM_EM_STTHRIO, EINVAL);
}
}
/*
** SM_GETINFO -- get information about the open file
**
** Parameters:
** fp -- file to get info for
** what -- type of info to get
** valp -- location to place found info
**
** Returns:
** Success: may or may not place info in 'valp' depending
** on 'what' value, and returns values >=0. Return
** value may be the obtained info
** Failure: usual sm_error code.
*/
static sm_ret_T
sm_thrgetinfo(sm_file_T *fp, int what, void *valp)
{
switch (what)
{
case SM_IO_WHAT_MODE:
return sm_thrgetmode(fp, (int *)valp);
case SM_IO_WHAT_FD:
return f_fd(*fp);
#if 0
case SM_IO_WHAT_NETFD:
valp = f_netfd(*fp);
return SM_SUCCESS;
#endif /* 0 */
/* XXX check state-threads code! */
case SM_IO_IS_READABLE:
if (st_netfd_poll(f_netfd(*fp), POLLIN, (st_utime_t) 0) == 0)
return 1;
return 0;
default:
return sm_error_perm(SM_EM_STTHRIO, EINVAL);
}
}
/*
** SM_THRFDOPEN -- open file by primitive 'fd' rather than pathname
**
** I/O function to handle fdopen() stdio equivalence. The rest of
** the functions are the same as the sm_stdopen() above.
**
** Parameters:
** fp -- the file pointer to be associated with the open
** name -- the primitive file descriptor for association
** flags -- indicates type of access methods
**
** Results:
** usual sm_error code.
*/
/* ARGSUSED3 */
static sm_ret_T
sm_thrfdopen(sm_file_T *fp, const void *info, int flags, va_list ap)
{
int fd;
st_netfd_t netfd;
fd = *((const int *) info);
#if 0
switch (flags)
{
case SM_IO_RDWR:
oflags = O_RDWR | O_CREAT;
break;
case SM_IO_RDONLY:
oflags = O_RDONLY;
break;
case SM_IO_WRONLY:
oflags = O_WRONLY | O_CREAT | O_TRUNC;
break;
default:
return sm_error_perm(SM_EM_STTHRIO, EINVAL);
}
#endif /* 0 */
netfd = st_netfd_open(fd);
if (netfd == NULL)
return sm_error_perm(SM_EM_STTHRIO, errno); /* ??? temp? */
f_fd(*fp) = fd;
assign_f_netfd(*fp, netfd);
return SM_SUCCESS;
}
/*
** SM_THRNETOPEN -- open file by netfd 'fd' rather than pathname
**
** Parameters:
** fp -- the file pointer to be associated with the open
** name -- the primitive file descriptor for association
** flags -- indicates type of access methods
**
** Results:
** usual sm_error code.
*/
/* ARGSUSED3 */
static sm_ret_T
sm_thrnetopen(sm_file_T *fp, const void *info, int flags, va_list ap)
{
st_netfd_t netfd;
netfd = *((st_netfd_t *) info);
f_fd(*fp) = st_netfd_fileno(netfd);
assign_f_netfd(*fp, netfd);
return SM_SUCCESS;
}
#if 0
/*
** SM_THRCLOSE -- close the file
**
** Parameters:
** fp -- the file pointer to close
** flags -- ignored
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_thrnetclose(sm_file_T *fp, int flags)
{
return SM_SUCCESS;
}
#endif /* 0 */
syntax highlighted by Code2HTML, v. 0.9.1