155714Skris/* crypto/bio/bss_file.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. 8280304Sjkim * 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). 15280304Sjkim * 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. 22280304Sjkim * 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 :-). 37280304Sjkim * 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)" 40280304Sjkim * 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. 52280304Sjkim * 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 59280304Sjkim/*- 60280304Sjkim * 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout 61280304Sjkim * with binary data (e.g. asn1parse -inform DER < xxx) under 62280304Sjkim * Windows 6355714Skris */ 6455714Skris 6555714Skris#ifndef HEADER_BSS_FILE_C 66280304Sjkim# define HEADER_BSS_FILE_C 6755714Skris 68280304Sjkim# if defined(__linux) || defined(__sun) || defined(__hpux) 69280304Sjkim/* 70280304Sjkim * Following definition aliases fopen to fopen64 on above mentioned 71280304Sjkim * platforms. This makes it possible to open and sequentially access files 72280304Sjkim * larger than 2GB from 32-bit application. It does not allow to traverse 73280304Sjkim * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit 74280304Sjkim * platform permits that, not with fseek/ftell. Not to mention that breaking 75280304Sjkim * 2GB limit for seeking would require surgery to *our* API. But sequential 76280304Sjkim * access suffices for practical cases when you can run into large files, 77280304Sjkim * such as fingerprinting, so we can let API alone. For reference, the list 78280304Sjkim * of 32-bit platforms which allow for sequential access of large files 79280304Sjkim * without extra "magic" comprise *BSD, Darwin, IRIX... 80160814Ssimon */ 81280304Sjkim# ifndef _FILE_OFFSET_BITS 82280304Sjkim# define _FILE_OFFSET_BITS 64 83280304Sjkim# endif 84280304Sjkim# endif 85160814Ssimon 86280304Sjkim# include <stdio.h> 87280304Sjkim# include <errno.h> 88280304Sjkim# include "cryptlib.h" 89280304Sjkim# include "bio_lcl.h" 90280304Sjkim# include <openssl/err.h> 9155714Skris 92280304Sjkim# if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) 93280304Sjkim# include <nwfileio.h> 94280304Sjkim# endif 95194206Ssimon 96280304Sjkim# if !defined(OPENSSL_NO_STDIO) 9755714Skris 9868651Skrisstatic int MS_CALLBACK file_write(BIO *h, const char *buf, int num); 9968651Skrisstatic int MS_CALLBACK file_read(BIO *h, char *buf, int size); 10068651Skrisstatic int MS_CALLBACK file_puts(BIO *h, const char *str); 10168651Skrisstatic int MS_CALLBACK file_gets(BIO *h, char *str, int size); 10268651Skrisstatic long MS_CALLBACK file_ctrl(BIO *h, int cmd, long arg1, void *arg2); 10355714Skrisstatic int MS_CALLBACK file_new(BIO *h); 10455714Skrisstatic int MS_CALLBACK file_free(BIO *data); 105280304Sjkimstatic BIO_METHOD methods_filep = { 106280304Sjkim BIO_TYPE_FILE, 107280304Sjkim "FILE pointer", 108280304Sjkim file_write, 109280304Sjkim file_read, 110280304Sjkim file_puts, 111280304Sjkim file_gets, 112280304Sjkim file_ctrl, 113280304Sjkim file_new, 114280304Sjkim file_free, 115280304Sjkim NULL, 116280304Sjkim}; 11755714Skris 118291721Sjkimstatic FILE *file_fopen(const char *filename, const char *mode) 119280304Sjkim{ 120280304Sjkim FILE *file = NULL; 12155714Skris 122280304Sjkim# if defined(_WIN32) && defined(CP_UTF8) 123280304Sjkim int sz, len_0 = (int)strlen(filename) + 1; 124280304Sjkim DWORD flags; 125238405Sjkim 126280304Sjkim /* 127280304Sjkim * Basically there are three cases to cover: a) filename is 128280304Sjkim * pure ASCII string; b) actual UTF-8 encoded string and 129280304Sjkim * c) locale-ized string, i.e. one containing 8-bit 130280304Sjkim * characters that are meaningful in current system locale. 131280304Sjkim * If filename is pure ASCII or real UTF-8 encoded string, 132280304Sjkim * MultiByteToWideChar succeeds and _wfopen works. If 133280304Sjkim * filename is locale-ized string, chances are that 134280304Sjkim * MultiByteToWideChar fails reporting 135280304Sjkim * ERROR_NO_UNICODE_TRANSLATION, in which case we fall 136280304Sjkim * back to fopen... 137280304Sjkim */ 138280304Sjkim if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS), 139280304Sjkim filename, len_0, NULL, 0)) > 0 || 140280304Sjkim (GetLastError() == ERROR_INVALID_FLAGS && 141280304Sjkim (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), 142280304Sjkim filename, len_0, NULL, 0)) > 0) 143280304Sjkim ) { 144280304Sjkim WCHAR wmode[8]; 145280304Sjkim WCHAR *wfilename = _alloca(sz * sizeof(WCHAR)); 146238405Sjkim 147280304Sjkim if (MultiByteToWideChar(CP_UTF8, flags, 148280304Sjkim filename, len_0, wfilename, sz) && 149280304Sjkim MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, 150280304Sjkim wmode, sizeof(wmode) / sizeof(wmode[0])) && 151280304Sjkim (file = _wfopen(wfilename, wmode)) == NULL && 152280304Sjkim (errno == ENOENT || errno == EBADF) 153280304Sjkim ) { 154280304Sjkim /* 155280304Sjkim * UTF-8 decode succeeded, but no file, filename 156280304Sjkim * could still have been locale-ized... 157280304Sjkim */ 158280304Sjkim file = fopen(filename, mode); 159280304Sjkim } 160280304Sjkim } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { 161280304Sjkim file = fopen(filename, mode); 162280304Sjkim } 163280304Sjkim# else 164280304Sjkim file = fopen(filename, mode); 165280304Sjkim# endif 166291721Sjkim return (file); 167291721Sjkim} 168291721Sjkim 169291721SjkimBIO *BIO_new_file(const char *filename, const char *mode) 170291721Sjkim{ 171291721Sjkim BIO *ret; 172291721Sjkim FILE *file = file_fopen(filename, mode); 173291721Sjkim 174280304Sjkim if (file == NULL) { 175280304Sjkim SYSerr(SYS_F_FOPEN, get_last_sys_error()); 176280304Sjkim ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); 177280304Sjkim if (errno == ENOENT) 178280304Sjkim BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); 179280304Sjkim else 180280304Sjkim BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); 181280304Sjkim return (NULL); 182280304Sjkim } 183280304Sjkim if ((ret = BIO_new(BIO_s_file())) == NULL) { 184280304Sjkim fclose(file); 185280304Sjkim return (NULL); 186280304Sjkim } 18755714Skris 188280304Sjkim BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage 189280304Sjkim * UPLINK */ 190280304Sjkim BIO_set_fp(ret, file, BIO_CLOSE); 191280304Sjkim return (ret); 192280304Sjkim} 19355714Skris 19455714SkrisBIO *BIO_new_fp(FILE *stream, int close_flag) 195280304Sjkim{ 196280304Sjkim BIO *ret; 19755714Skris 198280304Sjkim if ((ret = BIO_new(BIO_s_file())) == NULL) 199280304Sjkim return (NULL); 20055714Skris 201280304Sjkim BIO_set_flags(ret, BIO_FLAGS_UPLINK); /* redundant, left for 202280304Sjkim * documentation puposes */ 203280304Sjkim BIO_set_fp(ret, stream, close_flag); 204280304Sjkim return (ret); 205280304Sjkim} 20655714Skris 20755714SkrisBIO_METHOD *BIO_s_file(void) 208280304Sjkim{ 209280304Sjkim return (&methods_filep); 210280304Sjkim} 21155714Skris 21255714Skrisstatic int MS_CALLBACK file_new(BIO *bi) 213280304Sjkim{ 214280304Sjkim bi->init = 0; 215280304Sjkim bi->num = 0; 216280304Sjkim bi->ptr = NULL; 217280304Sjkim bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */ 218280304Sjkim return (1); 219280304Sjkim} 22055714Skris 22155714Skrisstatic int MS_CALLBACK file_free(BIO *a) 222280304Sjkim{ 223280304Sjkim if (a == NULL) 224280304Sjkim return (0); 225280304Sjkim if (a->shutdown) { 226280304Sjkim if ((a->init) && (a->ptr != NULL)) { 227280304Sjkim if (a->flags & BIO_FLAGS_UPLINK) 228280304Sjkim UP_fclose(a->ptr); 229280304Sjkim else 230280304Sjkim fclose(a->ptr); 231280304Sjkim a->ptr = NULL; 232280304Sjkim a->flags = BIO_FLAGS_UPLINK; 233280304Sjkim } 234280304Sjkim a->init = 0; 235280304Sjkim } 236280304Sjkim return (1); 237280304Sjkim} 238280304Sjkim 23955714Skrisstatic int MS_CALLBACK file_read(BIO *b, char *out, int outl) 240280304Sjkim{ 241280304Sjkim int ret = 0; 24255714Skris 243280304Sjkim if (b->init && (out != NULL)) { 244280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 245280304Sjkim ret = UP_fread(out, 1, (int)outl, b->ptr); 246280304Sjkim else 247280304Sjkim ret = fread(out, 1, (int)outl, (FILE *)b->ptr); 248280304Sjkim if (ret == 0 249280304Sjkim && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) : 250280304Sjkim ferror((FILE *)b->ptr)) { 251280304Sjkim SYSerr(SYS_F_FREAD, get_last_sys_error()); 252280304Sjkim BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB); 253280304Sjkim ret = -1; 254280304Sjkim } 255280304Sjkim } 256280304Sjkim return (ret); 257280304Sjkim} 25855714Skris 25968651Skrisstatic int MS_CALLBACK file_write(BIO *b, const char *in, int inl) 260280304Sjkim{ 261280304Sjkim int ret = 0; 26255714Skris 263280304Sjkim if (b->init && (in != NULL)) { 264280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 265280304Sjkim ret = UP_fwrite(in, (int)inl, 1, b->ptr); 266280304Sjkim else 267280304Sjkim ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr); 268280304Sjkim if (ret) 269280304Sjkim ret = inl; 270280304Sjkim /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */ 271280304Sjkim /* 272280304Sjkim * according to Tim Hudson <tjh@cryptsoft.com>, the commented out 273280304Sjkim * version above can cause 'inl' write calls under some stupid stdio 274280304Sjkim * implementations (VMS) 275280304Sjkim */ 276280304Sjkim } 277280304Sjkim return (ret); 278280304Sjkim} 27955714Skris 28068651Skrisstatic long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) 281280304Sjkim{ 282280304Sjkim long ret = 1; 283280304Sjkim FILE *fp = (FILE *)b->ptr; 284280304Sjkim FILE **fpp; 285280304Sjkim char p[4]; 28655714Skris 287280304Sjkim switch (cmd) { 288280304Sjkim case BIO_C_FILE_SEEK: 289280304Sjkim case BIO_CTRL_RESET: 290280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 291280304Sjkim ret = (long)UP_fseek(b->ptr, num, 0); 292280304Sjkim else 293280304Sjkim ret = (long)fseek(fp, num, 0); 294280304Sjkim break; 295280304Sjkim case BIO_CTRL_EOF: 296280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 297280304Sjkim ret = (long)UP_feof(fp); 298280304Sjkim else 299280304Sjkim ret = (long)feof(fp); 300280304Sjkim break; 301280304Sjkim case BIO_C_FILE_TELL: 302280304Sjkim case BIO_CTRL_INFO: 303280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 304280304Sjkim ret = UP_ftell(b->ptr); 305280304Sjkim else 306280304Sjkim ret = ftell(fp); 307280304Sjkim break; 308280304Sjkim case BIO_C_SET_FILE_PTR: 309280304Sjkim file_free(b); 310280304Sjkim b->shutdown = (int)num & BIO_CLOSE; 311280304Sjkim b->ptr = ptr; 312280304Sjkim b->init = 1; 313280304Sjkim# if BIO_FLAGS_UPLINK!=0 314280304Sjkim# if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) 315280304Sjkim# define _IOB_ENTRIES 20 316280304Sjkim# endif 317280304Sjkim# if defined(_IOB_ENTRIES) 318280304Sjkim /* Safety net to catch purely internal BIO_set_fp calls */ 319280304Sjkim if ((size_t)ptr >= (size_t)stdin && 320280304Sjkim (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES)) 321280304Sjkim BIO_clear_flags(b, BIO_FLAGS_UPLINK); 322280304Sjkim# endif 323280304Sjkim# endif 324280304Sjkim# ifdef UP_fsetmod 325280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 326280304Sjkim UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b')); 327280304Sjkim else 328280304Sjkim# endif 329280304Sjkim { 330280304Sjkim# if defined(OPENSSL_SYS_WINDOWS) 331280304Sjkim int fd = _fileno((FILE *)ptr); 332280304Sjkim if (num & BIO_FP_TEXT) 333280304Sjkim _setmode(fd, _O_TEXT); 334280304Sjkim else 335280304Sjkim _setmode(fd, _O_BINARY); 336280304Sjkim# elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) 337280304Sjkim int fd = fileno((FILE *)ptr); 338280304Sjkim /* Under CLib there are differences in file modes */ 339280304Sjkim if (num & BIO_FP_TEXT) 340280304Sjkim setmode(fd, O_TEXT); 341280304Sjkim else 342280304Sjkim setmode(fd, O_BINARY); 343280304Sjkim# elif defined(OPENSSL_SYS_MSDOS) 344280304Sjkim int fd = fileno((FILE *)ptr); 345280304Sjkim /* Set correct text/binary mode */ 346280304Sjkim if (num & BIO_FP_TEXT) 347280304Sjkim _setmode(fd, _O_TEXT); 348280304Sjkim /* Dangerous to set stdin/stdout to raw (unless redirected) */ 349280304Sjkim else { 350280304Sjkim if (fd == STDIN_FILENO || fd == STDOUT_FILENO) { 351280304Sjkim if (isatty(fd) <= 0) 352280304Sjkim _setmode(fd, _O_BINARY); 353280304Sjkim } else 354280304Sjkim _setmode(fd, _O_BINARY); 355280304Sjkim } 356280304Sjkim# elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN) 357280304Sjkim int fd = fileno((FILE *)ptr); 358280304Sjkim if (num & BIO_FP_TEXT) 359280304Sjkim setmode(fd, O_TEXT); 360280304Sjkim else 361280304Sjkim setmode(fd, O_BINARY); 362280304Sjkim# endif 363280304Sjkim } 364280304Sjkim break; 365280304Sjkim case BIO_C_SET_FILENAME: 366280304Sjkim file_free(b); 367280304Sjkim b->shutdown = (int)num & BIO_CLOSE; 368280304Sjkim if (num & BIO_FP_APPEND) { 369280304Sjkim if (num & BIO_FP_READ) 370280304Sjkim BUF_strlcpy(p, "a+", sizeof p); 371280304Sjkim else 372280304Sjkim BUF_strlcpy(p, "a", sizeof p); 373280304Sjkim } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) 374280304Sjkim BUF_strlcpy(p, "r+", sizeof p); 375280304Sjkim else if (num & BIO_FP_WRITE) 376280304Sjkim BUF_strlcpy(p, "w", sizeof p); 377280304Sjkim else if (num & BIO_FP_READ) 378280304Sjkim BUF_strlcpy(p, "r", sizeof p); 379280304Sjkim else { 380280304Sjkim BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE); 381280304Sjkim ret = 0; 382280304Sjkim break; 383280304Sjkim } 384280304Sjkim# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN) 385280304Sjkim if (!(num & BIO_FP_TEXT)) 386280304Sjkim strcat(p, "b"); 387280304Sjkim else 388280304Sjkim strcat(p, "t"); 389280304Sjkim# endif 390280304Sjkim# if defined(OPENSSL_SYS_NETWARE) 391280304Sjkim if (!(num & BIO_FP_TEXT)) 392280304Sjkim strcat(p, "b"); 393280304Sjkim else 394280304Sjkim strcat(p, "t"); 395280304Sjkim# endif 396291721Sjkim fp = file_fopen(ptr, p); 397280304Sjkim if (fp == NULL) { 398280304Sjkim SYSerr(SYS_F_FOPEN, get_last_sys_error()); 399280304Sjkim ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); 400280304Sjkim BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); 401280304Sjkim ret = 0; 402280304Sjkim break; 403280304Sjkim } 404280304Sjkim b->ptr = fp; 405280304Sjkim b->init = 1; 406280304Sjkim BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage 407280304Sjkim * UPLINK */ 408280304Sjkim break; 409280304Sjkim case BIO_C_GET_FILE_PTR: 410280304Sjkim /* the ptr parameter is actually a FILE ** in this case. */ 411280304Sjkim if (ptr != NULL) { 412280304Sjkim fpp = (FILE **)ptr; 413280304Sjkim *fpp = (FILE *)b->ptr; 414280304Sjkim } 415280304Sjkim break; 416280304Sjkim case BIO_CTRL_GET_CLOSE: 417280304Sjkim ret = (long)b->shutdown; 418280304Sjkim break; 419280304Sjkim case BIO_CTRL_SET_CLOSE: 420280304Sjkim b->shutdown = (int)num; 421280304Sjkim break; 422280304Sjkim case BIO_CTRL_FLUSH: 423280304Sjkim if (b->flags & BIO_FLAGS_UPLINK) 424280304Sjkim UP_fflush(b->ptr); 425280304Sjkim else 426280304Sjkim fflush((FILE *)b->ptr); 427280304Sjkim break; 428280304Sjkim case BIO_CTRL_DUP: 429280304Sjkim ret = 1; 430280304Sjkim break; 43155714Skris 432280304Sjkim case BIO_CTRL_WPENDING: 433280304Sjkim case BIO_CTRL_PENDING: 434280304Sjkim case BIO_CTRL_PUSH: 435280304Sjkim case BIO_CTRL_POP: 436280304Sjkim default: 437280304Sjkim ret = 0; 438280304Sjkim break; 439280304Sjkim } 440280304Sjkim return (ret); 441280304Sjkim} 44255714Skris 44355714Skrisstatic int MS_CALLBACK file_gets(BIO *bp, char *buf, int size) 444280304Sjkim{ 445280304Sjkim int ret = 0; 44655714Skris 447280304Sjkim buf[0] = '\0'; 448280304Sjkim if (bp->flags & BIO_FLAGS_UPLINK) { 449280304Sjkim if (!UP_fgets(buf, size, bp->ptr)) 450280304Sjkim goto err; 451280304Sjkim } else { 452280304Sjkim if (!fgets(buf, size, (FILE *)bp->ptr)) 453280304Sjkim goto err; 454280304Sjkim } 455280304Sjkim if (buf[0] != '\0') 456280304Sjkim ret = strlen(buf); 457280304Sjkim err: 458280304Sjkim return (ret); 459280304Sjkim} 46055714Skris 46168651Skrisstatic int MS_CALLBACK file_puts(BIO *bp, const char *str) 462280304Sjkim{ 463280304Sjkim int n, ret; 46455714Skris 465280304Sjkim n = strlen(str); 466280304Sjkim ret = file_write(bp, str, n); 467280304Sjkim return (ret); 468280304Sjkim} 46955714Skris 470280304Sjkim# endif /* OPENSSL_NO_STDIO */ 47155714Skris 472280304Sjkim#endif /* HEADER_BSS_FILE_C */ 473