plistutil: preserve binary data on Windows standard streams
diff --git a/test/Makefile.am b/test/Makefile.am
index f9f21e4..76d2373 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -84,7 +84,8 @@
 	ostep-strings.test \
 	ostep-comments.test \
 	ostep-invalid-types.test \
-	xml_behavior.test
+	xml_behavior.test \
+	plistutil-streams.test
 
 EXTRA_DIST = \
 	$(TESTS) \
@@ -136,7 +137,8 @@
 	data/o1.ostep \
 	data/o2.ostep \
 	data/o3.ostep \
-	data/test.strings
+	data/test.strings \
+	data/streams.plist
 
 TESTS_ENVIRONMENT = \
 	top_srcdir=$(top_srcdir) \
diff --git a/test/data/streams.plist b/test/data/streams.plist
new file mode 100644
index 0000000..b46a4af
--- /dev/null
+++ b/test/data/streams.plist
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<data>DQoa</data>
+</plist>
diff --git a/test/plistutil-streams.test b/test/plistutil-streams.test
new file mode 100755
index 0000000..ce3c516
--- /dev/null
+++ b/test/plistutil-streams.test
@@ -0,0 +1,34 @@
+## -*- sh -*-
+set -e
+
+DATASRC=$top_srcdir/test/data
+DATAOUT=$top_builddir/test/data
+PLISTUTIL=$top_builddir/tools/plistutil
+TESTFILE=$DATAOUT/plistutil-streams.test
+
+mkdir -p "$DATAOUT"
+
+# The data contains CR, LF and Ctrl-Z, which Windows text streams translate.
+"$PLISTUTIL" -i "$DATASRC/streams.plist" -f bin -o "$TESTFILE.bin"
+"$PLISTUTIL" -i "$TESTFILE.bin" -f xml -o "$TESTFILE.xml"
+
+echo "Checking binary stdout"
+"$PLISTUTIL" -i "$DATASRC/streams.plist" -f bin > "$TESTFILE.stdout.out"
+cmp "$TESTFILE.bin" "$TESTFILE.stdout.out"
+"$PLISTUTIL" -i "$DATASRC/streams.plist" -f bin -o - > "$TESTFILE.stdout.out"
+cmp "$TESTFILE.bin" "$TESTFILE.stdout.out"
+
+echo "Checking binary stdin"
+"$PLISTUTIL" -f xml -o "$TESTFILE.stdin.out" < "$TESTFILE.bin"
+cmp "$TESTFILE.xml" "$TESTFILE.stdin.out"
+cat "$TESTFILE.bin" | "$PLISTUTIL" -i - -f xml -o "$TESTFILE.stdin.out"
+cmp "$TESTFILE.xml" "$TESTFILE.stdin.out"
+
+echo "Checking binary stdin in print mode"
+"$PLISTUTIL" -p "$TESTFILE.bin" > "$TESTFILE.print.out"
+cat "$TESTFILE.bin" | "$PLISTUTIL" -p - > "$TESTFILE.stdin.out"
+cmp "$TESTFILE.print.out" "$TESTFILE.stdin.out"
+
+echo "Checking XML stdout"
+"$PLISTUTIL" -i "$TESTFILE.bin" -f xml > "$TESTFILE.stdout.out"
+cmp "$TESTFILE.xml" "$TESTFILE.stdout.out"
diff --git a/tools/plistutil.c b/tools/plistutil.c
index e2ea286..8a341d0 100644
--- a/tools/plistutil.c
+++ b/tools/plistutil.c
@@ -33,6 +33,10 @@
 #include <sys/stat.h>
 #include <getopt.h>
 #include <errno.h>
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#endif
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
@@ -266,6 +270,9 @@
 
     if (!options->in_file || !strcmp(options->in_file, "-"))
     {
+#ifdef _WIN32
+        _setmode(_fileno(stdin), _O_BINARY);
+#endif
         read_size = 0;
         plist_entire = malloc(sizeof(char) * read_capacity);
         if(plist_entire == NULL)
@@ -475,8 +482,12 @@
             fclose(oplist);
         }
         // if no output file specified, write to stdout
-        else
+        else {
+#ifdef _WIN32
+            _setmode(_fileno(stdout), _O_BINARY);
+#endif
             fwrite(plist_out, size, sizeof(char), stdout);
+        }
 
         free(plist_out);
     }