diff options
author | Richard Levitte <levitte@openssl.org> | 2015-09-06 10:51:04 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2015-09-06 13:34:48 +0200 |
commit | a412b8919821efd00121d28cf2441c5445bee602 (patch) | |
tree | a384a4c9da978a19b8c57ece5bbd490728fb83a4 /apps/apps.c | |
parent | 297172294c5bf2b94976ac6911d4d01176fb1921 (diff) | |
download | openssl-new-a412b8919821efd00121d28cf2441c5445bee602.tar.gz |
dup_bio_* and bio_open_* are utility functions and belong in apps.c
Reviewed-by: Tim Hudson <tjh@openssl.org>
Diffstat (limited to 'apps/apps.c')
-rw-r--r-- | apps/apps.c | 159 |
1 files changed, 158 insertions, 1 deletions
diff --git a/apps/apps.c b/apps/apps.c index f3b2d48f3a..0b5f9fd062 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -121,7 +121,13 @@ #if !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_WINCE) && !defined(NETWARE_CLIB) # include <strings.h> #endif -#include <sys/types.h> +#ifndef NO_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifndef OPENSSL_NO_POSIX_IO +# include <sys/stat.h> +# include <fcntl.h> +#endif #include <ctype.h> #include <errno.h> #include <openssl/err.h> @@ -2707,3 +2713,154 @@ int raw_write_stdout(const void *buf, int siz) return write(fileno(stdout), buf, siz); } #endif + +/* + * Centralized handling if input and output files with format specification + * The format is meant to show what the input and output is supposed to be, + * and is therefore a show of intent more than anything else. However, it + * does impact behavior on some platform, such as differentiating between + * text and binary input/output on non-Unix platforms + */ +BIO *dup_bio_in(void) +{ + return BIO_new_fp(stdin, BIO_NOCLOSE | BIO_FP_TEXT); +} + +BIO *dup_bio_out(void) +{ + BIO *b = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); +#ifdef OPENSSL_SYS_VMS + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + return b; +} + +void unbuffer(FILE *fp) +{ + setbuf(fp, NULL); +} + +static const char *modestr(char mode, int format) +{ + OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); + + switch (mode) { + case 'a': + return (format & B_FORMAT_TEXT) ? "a" : "ab"; + case 'r': + return (format & B_FORMAT_TEXT) ? "r" : "rb"; + case 'w': + return (format & B_FORMAT_TEXT) ? "w" : "wb"; + } + /* The assert above should make sure we never reach this point */ + return NULL; +} + +static const char *modeverb(char mode) +{ + switch (mode) { + case 'a': + return "appending"; + case 'r': + return "reading"; + case 'w': + return "writing"; + } + return "(doing something)"; +} + +/* + * Open a file for writing, owner-read-only. + */ +BIO *bio_open_owner(const char *filename, int format, int private) +{ + FILE *fp = NULL; + BIO *b = NULL; + int fd = -1, bflags, mode, binmode; + + if (!private || filename == NULL || strcmp(filename, "-") == 0) + return bio_open_default(filename, 'w', format); + + mode = O_WRONLY; +#ifdef O_CREAT + mode |= O_CREAT; +#endif +#ifdef O_TRUNC + mode |= O_TRUNC; +#endif + binmode = !(format & B_FORMAT_TEXT); + if (binmode) { +#ifdef O_BINARY + mode |= O_BINARY; +#elif defined(_O_BINARY) + mode |= _O_BINARY; +#endif + } + + fd = open(filename, mode, 0600); + if (fd < 0) + goto err; + fp = fdopen(fd, modestr('w', format)); + if (fp == NULL) + goto err; + bflags = BIO_CLOSE; + if (!binmode) + bflags |= BIO_FP_TEXT; + b = BIO_new_fp(fp, bflags); + if (b) + return b; + + err: + BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", + opt_getprog(), filename, strerror(errno)); + ERR_print_errors(bio_err); + /* If we have fp, then fdopen took over fd, so don't close both. */ + if (fp) + fclose(fp); + else if (fd >= 0) + close(fd); + return NULL; +} + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet) +{ + BIO *ret; + + if (filename == NULL || strcmp(filename, "-") == 0) { + ret = mode == 'r' ? dup_bio_in() : dup_bio_out(); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s, %s\n", + mode == 'r' ? "stdin" : "stdout", strerror(errno)); + } else { + ret = BIO_new_file(filename, modestr(mode, format)); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s for %s, %s\n", + filename, modeverb(mode), strerror(errno)); + } + ERR_print_errors(bio_err); + return NULL; +} + +BIO *bio_open_default(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 0); +} + +BIO *bio_open_default_quiet(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 1); +} + |