/* crypto/bio/bss_file.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* [including the GNU Public Licence.]
*/
+/*
+ * 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout
+ * with binary data (e.g. asn1parse -inform DER < xxx) under
+ * Windows
+ */
+
+#ifndef HEADER_BSS_FILE_C
+#define HEADER_BSS_FILE_C
+
+#if defined(__linux) || defined(__sun) || defined(__hpux)
+/* Following definition aliases fopen to fopen64 on above mentioned
+ * platforms. This makes it possible to open and sequentially access
+ * files larger than 2GB from 32-bit application. It does not allow to
+ * traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
+ * 32-bit platform permits that, not with fseek/ftell. Not to mention
+ * that breaking 2GB limit for seeking would require surgery to *our*
+ * API. But sequential access suffices for practical cases when you
+ * can run into large files, such as fingerprinting, so we can let API
+ * alone. For reference, the list of 32-bit platforms which allow for
+ * sequential access of large files without extra "magic" comprise *BSD,
+ * Darwin, IRIX...
+ */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#endif
+
#include <stdio.h>
#include <errno.h>
#include "cryptlib.h"
-#include "bio.h"
-#include "err.h"
-
-#ifndef NOPROTO
-static int MS_CALLBACK file_write(BIO *h,char *buf,int num);
-static int MS_CALLBACK file_read(BIO *h,char *buf,int size);
-static int MS_CALLBACK file_puts(BIO *h,char *str);
-static int MS_CALLBACK file_gets(BIO *h,char *str,int size);
-static long MS_CALLBACK file_ctrl(BIO *h,int cmd,long arg1,char *arg2);
-static int MS_CALLBACK file_new(BIO *h);
-static int MS_CALLBACK file_free(BIO *data);
-#else
-static int MS_CALLBACK file_write();
-static int MS_CALLBACK file_read();
-static int MS_CALLBACK file_puts();
-static int MS_CALLBACK file_gets();
-static long MS_CALLBACK file_ctrl();
-static int MS_CALLBACK file_new();
-static int MS_CALLBACK file_free();
+#include "bio_lcl.h"
+#include <openssl/err.h>
+
+#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
+#include <nwfileio.h>
#endif
+#if !defined(OPENSSL_NO_STDIO)
+
+static int MS_CALLBACK file_write(BIO *h, const char *buf, int num);
+static int MS_CALLBACK file_read(BIO *h, char *buf, int size);
+static int MS_CALLBACK file_puts(BIO *h, const char *str);
+static int MS_CALLBACK file_gets(BIO *h, char *str, int size);
+static long MS_CALLBACK file_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int MS_CALLBACK file_new(BIO *h);
+static int MS_CALLBACK file_free(BIO *data);
static BIO_METHOD methods_filep=
{
- BIO_TYPE_FILE,"FILE pointer",
+ BIO_TYPE_FILE,
+ "FILE pointer",
file_write,
file_read,
file_puts,
file_ctrl,
file_new,
file_free,
+ NULL,
};
-#if !defined(WIN16) || defined(APPS_WIN16)
-BIO *BIO_new_file(filename,mode)
-char *filename;
-char *mode;
+BIO *BIO_new_file(const char *filename, const char *mode)
{
- BIO *ret;
- FILE *file;
+ BIO *ret;
+ FILE *file=NULL;
- if ((file=fopen(filename,mode)) == NULL)
+#if defined(_WIN32) && defined(CP_UTF8)
+ int sz, len_0 = (int)strlen(filename)+1;
+ DWORD flags;
+
+ /*
+ * Basically there are three cases to cover: a) filename is
+ * pure ASCII string; b) actual UTF-8 encoded string and
+ * c) locale-ized string, i.e. one containing 8-bit
+ * characters that are meaningful in current system locale.
+ * If filename is pure ASCII or real UTF-8 encoded string,
+ * MultiByteToWideChar succeeds and _wfopen works. If
+ * filename is locale-ized string, chances are that
+ * MultiByteToWideChar fails reporting
+ * ERROR_NO_UNICODE_TRANSLATION, in which case we fall
+ * back to fopen...
+ */
+ if ((sz=MultiByteToWideChar(CP_UTF8,(flags=MB_ERR_INVALID_CHARS),
+ filename,len_0,NULL,0))>0 ||
+ (GetLastError()==ERROR_INVALID_FLAGS &&
+ (sz=MultiByteToWideChar(CP_UTF8,(flags=0),
+ filename,len_0,NULL,0))>0)
+ )
+ {
+ WCHAR wmode[8];
+ WCHAR *wfilename = _alloca(sz*sizeof(WCHAR));
+
+ if (MultiByteToWideChar(CP_UTF8,flags,
+ filename,len_0,wfilename,sz) &&
+ MultiByteToWideChar(CP_UTF8,0,mode,strlen(mode)+1,
+ wmode,sizeof(wmode)/sizeof(wmode[0])) &&
+ (file=_wfopen(wfilename,wmode))==NULL &&
+ (errno==ENOENT || errno==EBADF)
+ ) /* UTF-8 decode succeeded, but no file, filename
+ * could still have been locale-ized... */
+ file = fopen(filename,mode);
+ }
+ else if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION)
{
- SYSerr(SYS_F_FOPEN,errno);
- BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB);
+ file = fopen(filename,mode);
+ }
+#else
+ file=fopen(filename,mode);
+#endif
+ if (file == NULL)
+ {
+ SYSerr(SYS_F_FOPEN,get_last_sys_error());
+ ERR_add_error_data(5,"fopen('",filename,"','",mode,"')");
+ if (errno == ENOENT)
+ BIOerr(BIO_F_BIO_NEW_FILE,BIO_R_NO_SUCH_FILE);
+ else
+ BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB);
return(NULL);
}
-
if ((ret=BIO_new(BIO_s_file())) == NULL)
+ {
+ fclose(file);
return(NULL);
-#if 0
- if ((ret=BIO_new(BIO_s_file_internal_w16())) == NULL)
- return(NULL);
-#endif
+ }
+ BIO_clear_flags(ret,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
BIO_set_fp(ret,file,BIO_CLOSE);
return(ret);
}
-BIO *BIO_new_fp(stream,close_flag)
-FILE *stream;
-int close_flag;
+BIO *BIO_new_fp(FILE *stream, int close_flag)
{
BIO *ret;
if ((ret=BIO_new(BIO_s_file())) == NULL)
return(NULL);
-#if 0
- if ((ret=BIO_new(BIO_s_file_internal_w16())) == NULL)
-#endif
+ BIO_set_flags(ret,BIO_FLAGS_UPLINK); /* redundant, left for documentation puposes */
BIO_set_fp(ret,stream,close_flag);
return(ret);
}
-#endif /* !APPS_WIN16 */
-
-#if !defined(WIN16) || defined(APPS_WIN16)
-BIO_METHOD *BIO_s_file()
+BIO_METHOD *BIO_s_file(void)
{
return(&methods_filep);
}
-#else
-
-BIO_METHOD *BIO_s_file_internal_w16()
- {
- return(&methods_filep);
- }
-
-#endif
-
-static int MS_CALLBACK file_new(bi)
-BIO *bi;
+static int MS_CALLBACK file_new(BIO *bi)
{
bi->init=0;
bi->num=0;
bi->ptr=NULL;
+ bi->flags=BIO_FLAGS_UPLINK; /* default to UPLINK */
return(1);
}
-static int MS_CALLBACK file_free(a)
-BIO *a;
+static int MS_CALLBACK file_free(BIO *a)
{
if (a == NULL) return(0);
if (a->shutdown)
{
if ((a->init) && (a->ptr != NULL))
{
- fclose((FILE *)a->ptr);
+ if (a->flags&BIO_FLAGS_UPLINK)
+ UP_fclose (a->ptr);
+ else
+ fclose (a->ptr);
a->ptr=NULL;
+ a->flags=BIO_FLAGS_UPLINK;
}
a->init=0;
}
return(1);
}
-static int MS_CALLBACK file_read(b,out,outl)
-BIO *b;
-char *out;
-int outl;
+static int MS_CALLBACK file_read(BIO *b, char *out, int outl)
{
int ret=0;
if (b->init && (out != NULL))
{
- ret=fread(out,1,(int)outl,(FILE *)b->ptr);
+ if (b->flags&BIO_FLAGS_UPLINK)
+ ret=UP_fread(out,1,(int)outl,b->ptr);
+ else
+ ret=fread(out,1,(int)outl,(FILE *)b->ptr);
+ if(ret == 0 && (b->flags&BIO_FLAGS_UPLINK)?UP_ferror((FILE *)b->ptr):ferror((FILE *)b->ptr))
+ {
+ SYSerr(SYS_F_FREAD,get_last_sys_error());
+ BIOerr(BIO_F_FILE_READ,ERR_R_SYS_LIB);
+ ret=-1;
+ }
}
return(ret);
}
-static int MS_CALLBACK file_write(b,in,inl)
-BIO *b;
-char *in;
-int inl;
+static int MS_CALLBACK file_write(BIO *b, const char *in, int inl)
{
int ret=0;
if (b->init && (in != NULL))
{
- if (fwrite(in,(int)inl,1,(FILE *)b->ptr))
+ if (b->flags&BIO_FLAGS_UPLINK)
+ ret=UP_fwrite(in,(int)inl,1,b->ptr);
+ else
+ ret=fwrite(in,(int)inl,1,(FILE *)b->ptr);
+ if (ret)
ret=inl;
/* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */
- /* acording to Tim Hudson <tjh@cryptsoft.com>, the commented
+ /* according to Tim Hudson <tjh@cryptsoft.com>, the commented
* out version above can cause 'inl' write calls under
* some stupid stdio implementations (VMS) */
}
return(ret);
}
-static long MS_CALLBACK file_ctrl(b,cmd,num,ptr)
-BIO *b;
-int cmd;
-long num;
-char *ptr;
+static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret=1;
FILE *fp=(FILE *)b->ptr;
switch (cmd)
{
+ case BIO_C_FILE_SEEK:
case BIO_CTRL_RESET:
- ret=(long)fseek(fp,num,0);
+ if (b->flags&BIO_FLAGS_UPLINK)
+ ret=(long)UP_fseek(b->ptr,num,0);
+ else
+ ret=(long)fseek(fp,num,0);
break;
case BIO_CTRL_EOF:
- ret=(long)feof(fp);
+ if (b->flags&BIO_FLAGS_UPLINK)
+ ret=(long)UP_feof(fp);
+ else
+ ret=(long)feof(fp);
break;
+ case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
- ret=ftell(fp);
+ if (b->flags&BIO_FLAGS_UPLINK)
+ ret=UP_ftell(b->ptr);
+ else
+ ret=ftell(fp);
break;
case BIO_C_SET_FILE_PTR:
file_free(b);
- b->shutdown=(int)num;
- b->ptr=(char *)ptr;
+ b->shutdown=(int)num&BIO_CLOSE;
+ b->ptr=ptr;
b->init=1;
+#if BIO_FLAGS_UPLINK!=0
+#if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
+#define _IOB_ENTRIES 20
+#endif
+#if defined(_IOB_ENTRIES)
+ /* Safety net to catch purely internal BIO_set_fp calls */
+ if ((size_t)ptr >= (size_t)stdin &&
+ (size_t)ptr < (size_t)(stdin+_IOB_ENTRIES))
+ BIO_clear_flags(b,BIO_FLAGS_UPLINK);
+#endif
+#endif
+#ifdef UP_fsetmod
+ if (b->flags&BIO_FLAGS_UPLINK)
+ UP_fsetmod(b->ptr,(char)((num&BIO_FP_TEXT)?'t':'b'));
+ else
+#endif
+ {
+#if defined(OPENSSL_SYS_WINDOWS)
+ int fd = _fileno((FILE*)ptr);
+ if (num & BIO_FP_TEXT)
+ _setmode(fd,_O_TEXT);
+ else
+ _setmode(fd,_O_BINARY);
+#elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
+ int fd = fileno((FILE*)ptr);
+ /* Under CLib there are differences in file modes */
+ if (num & BIO_FP_TEXT)
+ setmode(fd,O_TEXT);
+ else
+ setmode(fd,O_BINARY);
+#elif defined(OPENSSL_SYS_MSDOS)
+ int fd = fileno((FILE*)ptr);
+ /* Set correct text/binary mode */
+ if (num & BIO_FP_TEXT)
+ _setmode(fd,_O_TEXT);
+ /* Dangerous to set stdin/stdout to raw (unless redirected) */
+ else
+ {
+ if (fd == STDIN_FILENO || fd == STDOUT_FILENO)
+ {
+ if (isatty(fd) <= 0)
+ _setmode(fd,_O_BINARY);
+ }
+ else
+ _setmode(fd,_O_BINARY);
+ }
+#elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
+ int fd = fileno((FILE*)ptr);
+ if (num & BIO_FP_TEXT)
+ setmode(fd, O_TEXT);
+ else
+ setmode(fd, O_BINARY);
+#endif
+ }
break;
case BIO_C_SET_FILENAME:
file_free(b);
if (num & BIO_FP_APPEND)
{
if (num & BIO_FP_READ)
- strcpy(p,"a+");
- else strcpy(p,"a");
+ BUF_strlcpy(p,"a+",sizeof p);
+ else BUF_strlcpy(p,"a",sizeof p);
}
else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
- strcpy(p,"r+");
+ BUF_strlcpy(p,"r+",sizeof p);
else if (num & BIO_FP_WRITE)
- strcpy(p,"w");
+ BUF_strlcpy(p,"w",sizeof p);
else if (num & BIO_FP_READ)
- strcpy(p,"r");
+ BUF_strlcpy(p,"r",sizeof p);
else
{
BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE);
ret=0;
break;
}
-#if defined(MSDOS) || defined(WINDOWS)
+#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
+ if (!(num & BIO_FP_TEXT))
+ strcat(p,"b");
+ else
+ strcat(p,"t");
+#endif
+#if defined(OPENSSL_SYS_NETWARE)
if (!(num & BIO_FP_TEXT))
strcat(p,"b");
else
fp=fopen(ptr,p);
if (fp == NULL)
{
- SYSerr(SYS_F_FOPEN,errno);
+ SYSerr(SYS_F_FOPEN,get_last_sys_error());
+ ERR_add_error_data(5,"fopen('",ptr,"','",p,"')");
BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB);
ret=0;
break;
}
- b->ptr=(char *)fp;
+ b->ptr=fp;
b->init=1;
+ BIO_clear_flags(b,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */
break;
case BIO_C_GET_FILE_PTR:
/* the ptr parameter is actually a FILE ** in this case. */
b->shutdown=(int)num;
break;
case BIO_CTRL_FLUSH:
- fflush((FILE *)b->ptr);
+ if (b->flags&BIO_FLAGS_UPLINK)
+ UP_fflush(b->ptr);
+ else
+ fflush((FILE *)b->ptr);
break;
case BIO_CTRL_DUP:
ret=1;
return(ret);
}
-static int MS_CALLBACK file_gets(bp,buf,size)
-BIO *bp;
-char *buf;
-int size;
+static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size)
{
int ret=0;
buf[0]='\0';
- fgets(buf,size,(FILE *)bp->ptr);
+ if (bp->flags&BIO_FLAGS_UPLINK)
+ {
+ if (!UP_fgets(buf,size,bp->ptr))
+ goto err;
+ }
+ else
+ {
+ if (!fgets(buf,size,(FILE *)bp->ptr))
+ goto err;
+ }
if (buf[0] != '\0')
ret=strlen(buf);
+ err:
return(ret);
}
-static int MS_CALLBACK file_puts(bp,str)
-BIO *bp;
-char *str;
+static int MS_CALLBACK file_puts(BIO *bp, const char *str)
{
int n,ret;
return(ret);
}
+#endif /* OPENSSL_NO_STDIO */
+
+#endif /* HEADER_BSS_FILE_C */
+
+