1 /* crypto/bio/bss_file.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
60 * 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout
61 * with binary data (e.g. asn1parse -inform DER < xxx) under
65 #ifndef HEADER_BSS_FILE_C
66 #define HEADER_BSS_FILE_C
68 #if defined(__linux) || defined(__sun) || defined(__hpux)
69 /* Following definition aliases fopen to fopen64 on above mentioned
70 * platforms. This makes it possible to open and sequentially access
71 * files larger than 2GB from 32-bit application. It does not allow to
72 * traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
73 * 32-bit platform permits that, not with fseek/ftell. Not to mention
74 * that breaking 2GB limit for seeking would require surgery to *our*
75 * API. But sequential access suffices for practical cases when you
76 * can run into large files, such as fingerprinting, so we can let API
77 * alone. For reference, the list of 32-bit platforms which allow for
78 * sequential access of large files without extra "magic" comprise *BSD,
81 #ifndef _FILE_OFFSET_BITS
82 #define _FILE_OFFSET_BITS 64
90 #include <openssl/err.h>
92 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
96 #if !defined(OPENSSL_NO_STDIO)
98 static int file_write(BIO
*h
, const char *buf
, int num
);
99 static int file_read(BIO
*h
, char *buf
, int size
);
100 static int file_puts(BIO
*h
, const char *str
);
101 static int file_gets(BIO
*h
, char *str
, int size
);
102 static long file_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
103 static int file_new(BIO
*h
);
104 static int file_free(BIO
*data
);
105 static BIO_METHOD methods_filep
=
119 BIO
*BIO_new_file(const char *filename
, const char *mode
)
124 #if defined(_WIN32) && defined(CP_UTF8)
125 int sz
, len_0
= (int)strlen(filename
)+1;
129 * Basically there are three cases to cover: a) filename is
130 * pure ASCII string; b) actual UTF-8 encoded string and
131 * c) locale-ized string, i.e. one containing 8-bit
132 * characters that are meaningful in current system locale.
133 * If filename is pure ASCII or real UTF-8 encoded string,
134 * MultiByteToWideChar succeeds and _wfopen works. If
135 * filename is locale-ized string, chances are that
136 * MultiByteToWideChar fails reporting
137 * ERROR_NO_UNICODE_TRANSLATION, in which case we fall
140 if ((sz
=MultiByteToWideChar(CP_UTF8
,(flags
=MB_ERR_INVALID_CHARS
),
141 filename
,len_0
,NULL
,0))>0 ||
142 (GetLastError()==ERROR_INVALID_FLAGS
&&
143 (sz
=MultiByteToWideChar(CP_UTF8
,(flags
=0),
144 filename
,len_0
,NULL
,0))>0)
148 WCHAR
*wfilename
= _alloca(sz
*sizeof(WCHAR
));
150 if (MultiByteToWideChar(CP_UTF8
,flags
,
151 filename
,len_0
,wfilename
,sz
) &&
152 MultiByteToWideChar(CP_UTF8
,0,mode
,strlen(mode
)+1,
153 wmode
,sizeof(wmode
)/sizeof(wmode
[0])) &&
154 (file
=_wfopen(wfilename
,wmode
))==NULL
&&
155 (errno
==ENOENT
|| errno
==EBADF
)
159 * UTF-8 decode succeeded, but no file, filename
160 * could still have been locale-ized...
162 file
= fopen(filename
,mode
);
165 else if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION
)
167 file
= fopen(filename
,mode
);
170 file
=fopen(filename
,mode
);
174 SYSerr(SYS_F_FOPEN
,get_last_sys_error());
175 ERR_add_error_data(5,"fopen('",filename
,"','",mode
,"')");
177 BIOerr(BIO_F_BIO_NEW_FILE
,BIO_R_NO_SUCH_FILE
);
179 BIOerr(BIO_F_BIO_NEW_FILE
,ERR_R_SYS_LIB
);
182 if ((ret
=BIO_new(BIO_s_file())) == NULL
)
188 BIO_clear_flags(ret
,BIO_FLAGS_UPLINK
); /* we did fopen -> we disengage UPLINK */
189 BIO_set_fp(ret
,file
,BIO_CLOSE
);
193 BIO
*BIO_new_fp(FILE *stream
, int close_flag
)
197 if ((ret
=BIO_new(BIO_s_file())) == NULL
)
200 BIO_set_flags(ret
,BIO_FLAGS_UPLINK
); /* redundant, left for documentation puposes */
201 BIO_set_fp(ret
,stream
,close_flag
);
205 BIO_METHOD
*BIO_s_file(void)
207 return(&methods_filep
);
210 static int file_new(BIO
*bi
)
215 bi
->flags
=BIO_FLAGS_UPLINK
; /* default to UPLINK */
219 static int file_free(BIO
*a
)
221 if (a
== NULL
) return(0);
224 if ((a
->init
) && (a
->ptr
!= NULL
))
226 if (a
->flags
&BIO_FLAGS_UPLINK
)
231 a
->flags
=BIO_FLAGS_UPLINK
;
238 static int file_read(BIO
*b
, char *out
, int outl
)
242 if (b
->init
&& (out
!= NULL
))
244 if (b
->flags
&BIO_FLAGS_UPLINK
)
245 ret
=UP_fread(out
,1,(int)outl
,b
->ptr
);
247 ret
=fread(out
,1,(int)outl
,(FILE *)b
->ptr
);
248 if(ret
== 0 && (b
->flags
&BIO_FLAGS_UPLINK
)?UP_ferror((FILE *)b
->ptr
):ferror((FILE *)b
->ptr
))
250 SYSerr(SYS_F_FREAD
,get_last_sys_error());
251 BIOerr(BIO_F_FILE_READ
,ERR_R_SYS_LIB
);
258 static int file_write(BIO
*b
, const char *in
, int inl
)
262 if (b
->init
&& (in
!= NULL
))
264 if (b
->flags
&BIO_FLAGS_UPLINK
)
265 ret
=UP_fwrite(in
,(int)inl
,1,b
->ptr
);
267 ret
=fwrite(in
,(int)inl
,1,(FILE *)b
->ptr
);
270 /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */
271 /* according to Tim Hudson <tjh@cryptsoft.com>, the commented
272 * out version above can cause 'inl' write calls under
273 * some stupid stdio implementations (VMS) */
278 static long file_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
281 FILE *fp
=(FILE *)b
->ptr
;
287 case BIO_C_FILE_SEEK
:
289 if (b
->flags
&BIO_FLAGS_UPLINK
)
290 ret
=(long)UP_fseek(b
->ptr
,num
,0);
292 ret
=(long)fseek(fp
,num
,0);
295 if (b
->flags
&BIO_FLAGS_UPLINK
)
296 ret
=(long)UP_feof(fp
);
300 case BIO_C_FILE_TELL
:
302 if (b
->flags
&BIO_FLAGS_UPLINK
)
303 ret
=UP_ftell(b
->ptr
);
307 case BIO_C_SET_FILE_PTR
:
309 b
->shutdown
=(int)num
&BIO_CLOSE
;
312 #if BIO_FLAGS_UPLINK!=0
313 #if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
314 #define _IOB_ENTRIES 20
316 #if defined(_IOB_ENTRIES)
317 /* Safety net to catch purely internal BIO_set_fp calls */
318 if ((size_t)ptr
>= (size_t)stdin
&&
319 (size_t)ptr
< (size_t)(stdin
+_IOB_ENTRIES
))
320 BIO_clear_flags(b
,BIO_FLAGS_UPLINK
);
324 if (b
->flags
&BIO_FLAGS_UPLINK
)
325 UP_fsetmod(b
->ptr
,(char)((num
&BIO_FP_TEXT
)?'t':'b'));
329 #if defined(OPENSSL_SYS_WINDOWS)
330 int fd
= _fileno((FILE*)ptr
);
331 if (num
& BIO_FP_TEXT
)
332 _setmode(fd
,_O_TEXT
);
334 _setmode(fd
,_O_BINARY
);
335 #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
336 int fd
= fileno((FILE*)ptr
);
337 /* Under CLib there are differences in file modes */
338 if (num
& BIO_FP_TEXT
)
341 setmode(fd
,O_BINARY
);
342 #elif defined(OPENSSL_SYS_MSDOS)
343 int fd
= fileno((FILE*)ptr
);
344 /* Set correct text/binary mode */
345 if (num
& BIO_FP_TEXT
)
346 _setmode(fd
,_O_TEXT
);
347 /* Dangerous to set stdin/stdout to raw (unless redirected) */
350 if (fd
== STDIN_FILENO
|| fd
== STDOUT_FILENO
)
353 _setmode(fd
,_O_BINARY
);
356 _setmode(fd
,_O_BINARY
);
358 #elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
359 int fd
= fileno((FILE*)ptr
);
360 if (num
& BIO_FP_TEXT
)
363 setmode(fd
, O_BINARY
);
367 case BIO_C_SET_FILENAME
:
369 b
->shutdown
=(int)num
&BIO_CLOSE
;
370 if (num
& BIO_FP_APPEND
)
372 if (num
& BIO_FP_READ
)
373 BUF_strlcpy(p
,"a+",sizeof p
);
374 else BUF_strlcpy(p
,"a",sizeof p
);
376 else if ((num
& BIO_FP_READ
) && (num
& BIO_FP_WRITE
))
377 BUF_strlcpy(p
,"r+",sizeof p
);
378 else if (num
& BIO_FP_WRITE
)
379 BUF_strlcpy(p
,"w",sizeof p
);
380 else if (num
& BIO_FP_READ
)
381 BUF_strlcpy(p
,"r",sizeof p
);
384 BIOerr(BIO_F_FILE_CTRL
,BIO_R_BAD_FOPEN_MODE
);
388 #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN)
389 if (!(num
& BIO_FP_TEXT
))
394 #if defined(OPENSSL_SYS_NETWARE)
395 if (!(num
& BIO_FP_TEXT
))
403 SYSerr(SYS_F_FOPEN
,get_last_sys_error());
404 ERR_add_error_data(5,"fopen('",ptr
,"','",p
,"')");
405 BIOerr(BIO_F_FILE_CTRL
,ERR_R_SYS_LIB
);
411 BIO_clear_flags(b
,BIO_FLAGS_UPLINK
); /* we did fopen -> we disengage UPLINK */
413 case BIO_C_GET_FILE_PTR
:
414 /* the ptr parameter is actually a FILE ** in this case. */
421 case BIO_CTRL_GET_CLOSE
:
422 ret
=(long)b
->shutdown
;
424 case BIO_CTRL_SET_CLOSE
:
425 b
->shutdown
=(int)num
;
428 if (b
->flags
&BIO_FLAGS_UPLINK
)
431 fflush((FILE *)b
->ptr
);
437 case BIO_CTRL_WPENDING
:
438 case BIO_CTRL_PENDING
:
448 static int file_gets(BIO
*bp
, char *buf
, int size
)
453 if (bp
->flags
&BIO_FLAGS_UPLINK
)
455 if (!UP_fgets(buf
,size
,bp
->ptr
))
460 if (!fgets(buf
,size
,(FILE *)bp
->ptr
))
469 static int file_puts(BIO
*bp
, const char *str
)
474 ret
=file_write(bp
,str
,n
);
478 #endif /* OPENSSL_NO_STDIO */
480 #endif /* HEADER_BSS_FILE_C */