aboutsummaryrefslogtreecommitdiffstats
path: root/apps/apps.c
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2015-09-06 10:51:04 +0200
committerRichard Levitte <levitte@openssl.org>2015-09-06 13:34:48 +0200
commita412b8919821efd00121d28cf2441c5445bee602 (patch)
treea384a4c9da978a19b8c57ece5bbd490728fb83a4 /apps/apps.c
parent297172294c5bf2b94976ac6911d4d01176fb1921 (diff)
downloadopenssl-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.c159
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);
+}
+