bss_fd.c revision 109998
155714Skris/* crypto/bio/bss_fd.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59109998Smarkm#include <stdio.h>
60109998Smarkm#include <errno.h>
61109998Smarkm#define USE_SOCKETS
62109998Smarkm#include "cryptlib.h"
63109998Smarkm#include <openssl/bio.h>
6455714Skris
65109998Smarkmstatic int fd_write(BIO *h, const char *buf, int num);
66109998Smarkmstatic int fd_read(BIO *h, char *buf, int size);
67109998Smarkmstatic int fd_puts(BIO *h, const char *str);
68109998Smarkmstatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
69109998Smarkmstatic int fd_new(BIO *h);
70109998Smarkmstatic int fd_free(BIO *data);
71109998Smarkmint BIO_fd_should_retry(int s);
72109998Smarkm
73109998Smarkmstatic BIO_METHOD methods_fdp=
74109998Smarkm	{
75109998Smarkm	BIO_TYPE_FD,"file descriptor",
76109998Smarkm	fd_write,
77109998Smarkm	fd_read,
78109998Smarkm	fd_puts,
79109998Smarkm	NULL, /* fd_gets, */
80109998Smarkm	fd_ctrl,
81109998Smarkm	fd_new,
82109998Smarkm	fd_free,
83109998Smarkm	NULL,
84109998Smarkm	};
85109998Smarkm
86109998SmarkmBIO_METHOD *BIO_s_fd(void)
87109998Smarkm	{
88109998Smarkm	return(&methods_fdp);
89109998Smarkm	}
90109998Smarkm
91109998SmarkmBIO *BIO_new_fd(int fd,int close_flag)
92109998Smarkm	{
93109998Smarkm	BIO *ret;
94109998Smarkm	ret=BIO_new(BIO_s_fd());
95109998Smarkm	if (ret == NULL) return(NULL);
96109998Smarkm	BIO_set_fd(ret,fd,close_flag);
97109998Smarkm	return(ret);
98109998Smarkm	}
99109998Smarkm
100109998Smarkmstatic int fd_new(BIO *bi)
101109998Smarkm	{
102109998Smarkm	bi->init=0;
103109998Smarkm	bi->num=0;
104109998Smarkm	bi->ptr=NULL;
105109998Smarkm	bi->flags=0;
106109998Smarkm	return(1);
107109998Smarkm	}
108109998Smarkm
109109998Smarkmstatic int fd_free(BIO *a)
110109998Smarkm	{
111109998Smarkm	if (a == NULL) return(0);
112109998Smarkm	if (a->shutdown)
113109998Smarkm		{
114109998Smarkm		if (a->init)
115109998Smarkm			{
116109998Smarkm			close(a->num);
117109998Smarkm			}
118109998Smarkm		a->init=0;
119109998Smarkm		a->flags=0;
120109998Smarkm		}
121109998Smarkm	return(1);
122109998Smarkm	}
123109998Smarkm
124109998Smarkmstatic int fd_read(BIO *b, char *out,int outl)
125109998Smarkm	{
126109998Smarkm	int ret=0;
127109998Smarkm
128109998Smarkm	if (out != NULL)
129109998Smarkm		{
130109998Smarkm		clear_sys_error();
131109998Smarkm		ret=read(b->num,out,outl);
132109998Smarkm		BIO_clear_retry_flags(b);
133109998Smarkm		if (ret <= 0)
134109998Smarkm			{
135109998Smarkm			if (BIO_fd_should_retry(ret))
136109998Smarkm				BIO_set_retry_read(b);
137109998Smarkm			}
138109998Smarkm		}
139109998Smarkm	return(ret);
140109998Smarkm	}
141109998Smarkm
142109998Smarkmstatic int fd_write(BIO *b, const char *in, int inl)
143109998Smarkm	{
144109998Smarkm	int ret;
145109998Smarkm	clear_sys_error();
146109998Smarkm	ret=write(b->num,in,inl);
147109998Smarkm	BIO_clear_retry_flags(b);
148109998Smarkm	if (ret <= 0)
149109998Smarkm		{
150109998Smarkm		if (BIO_fd_should_retry(ret))
151109998Smarkm			BIO_set_retry_write(b);
152109998Smarkm		}
153109998Smarkm	return(ret);
154109998Smarkm	}
155109998Smarkm
156109998Smarkmstatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr)
157109998Smarkm	{
158109998Smarkm	long ret=1;
159109998Smarkm	int *ip;
160109998Smarkm
161109998Smarkm	switch (cmd)
162109998Smarkm		{
163109998Smarkm	case BIO_CTRL_RESET:
164109998Smarkm		num=0;
165109998Smarkm	case BIO_C_FILE_SEEK:
166109998Smarkm		ret=(long)lseek(b->num,num,0);
167109998Smarkm		break;
168109998Smarkm	case BIO_C_FILE_TELL:
169109998Smarkm	case BIO_CTRL_INFO:
170109998Smarkm		ret=(long)lseek(b->num,0,1);
171109998Smarkm		break;
172109998Smarkm	case BIO_C_SET_FD:
173109998Smarkm		fd_free(b);
174109998Smarkm		b->num= *((int *)ptr);
175109998Smarkm		b->shutdown=(int)num;
176109998Smarkm		b->init=1;
177109998Smarkm		break;
178109998Smarkm	case BIO_C_GET_FD:
179109998Smarkm		if (b->init)
180109998Smarkm			{
181109998Smarkm			ip=(int *)ptr;
182109998Smarkm			if (ip != NULL) *ip=b->num;
183109998Smarkm			ret=b->num;
184109998Smarkm			}
185109998Smarkm		else
186109998Smarkm			ret= -1;
187109998Smarkm		break;
188109998Smarkm	case BIO_CTRL_GET_CLOSE:
189109998Smarkm		ret=b->shutdown;
190109998Smarkm		break;
191109998Smarkm	case BIO_CTRL_SET_CLOSE:
192109998Smarkm		b->shutdown=(int)num;
193109998Smarkm		break;
194109998Smarkm	case BIO_CTRL_PENDING:
195109998Smarkm	case BIO_CTRL_WPENDING:
196109998Smarkm		ret=0;
197109998Smarkm		break;
198109998Smarkm	case BIO_CTRL_DUP:
199109998Smarkm	case BIO_CTRL_FLUSH:
200109998Smarkm		ret=1;
201109998Smarkm		break;
202109998Smarkm	default:
203109998Smarkm		ret=0;
204109998Smarkm		break;
205109998Smarkm		}
206109998Smarkm	return(ret);
207109998Smarkm	}
208109998Smarkm
209109998Smarkmstatic int fd_puts(BIO *bp, const char *str)
210109998Smarkm	{
211109998Smarkm	int n,ret;
212109998Smarkm
213109998Smarkm	n=strlen(str);
214109998Smarkm	ret=fd_write(bp,str,n);
215109998Smarkm	return(ret);
216109998Smarkm	}
217109998Smarkm
218109998Smarkmint BIO_fd_should_retry(int i)
219109998Smarkm	{
220109998Smarkm	int err;
221109998Smarkm
222109998Smarkm	if ((i == 0) || (i == -1))
223109998Smarkm		{
224109998Smarkm		err=get_last_sys_error();
225109998Smarkm
226109998Smarkm#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */
227109998Smarkm		if ((i == -1) && (err == 0))
228109998Smarkm			return(1);
229109998Smarkm#endif
230109998Smarkm
231109998Smarkm		return(BIO_fd_non_fatal_error(err));
232109998Smarkm		}
233109998Smarkm	return(0);
234109998Smarkm	}
235109998Smarkm
236109998Smarkmint BIO_fd_non_fatal_error(int err)
237109998Smarkm	{
238109998Smarkm	switch (err)
239109998Smarkm		{
240109998Smarkm
241109998Smarkm#ifdef EWOULDBLOCK
242109998Smarkm# ifdef WSAEWOULDBLOCK
243109998Smarkm#  if WSAEWOULDBLOCK != EWOULDBLOCK
244109998Smarkm	case EWOULDBLOCK:
245109998Smarkm#  endif
246109998Smarkm# else
247109998Smarkm	case EWOULDBLOCK:
248109998Smarkm# endif
249109998Smarkm#endif
250109998Smarkm
251109998Smarkm#if defined(ENOTCONN)
252109998Smarkm	case ENOTCONN:
253109998Smarkm#endif
254109998Smarkm
255109998Smarkm#ifdef EINTR
256109998Smarkm	case EINTR:
257109998Smarkm#endif
258109998Smarkm
259109998Smarkm#ifdef EAGAIN
260109998Smarkm#if EWOULDBLOCK != EAGAIN
261109998Smarkm	case EAGAIN:
262109998Smarkm# endif
263109998Smarkm#endif
264109998Smarkm
265109998Smarkm#ifdef EPROTO
266109998Smarkm	case EPROTO:
267109998Smarkm#endif
268109998Smarkm
269109998Smarkm#ifdef EINPROGRESS
270109998Smarkm	case EINPROGRESS:
271109998Smarkm#endif
272109998Smarkm
273109998Smarkm#ifdef EALREADY
274109998Smarkm	case EALREADY:
275109998Smarkm#endif
276109998Smarkm		return(1);
277109998Smarkm		/* break; */
278109998Smarkm	default:
279109998Smarkm		break;
280109998Smarkm		}
281109998Smarkm	return(0);
282109998Smarkm	}
283