From 4451168e5d1ea26560899e9a9733b3a3f1853050 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 16 Sep 2011 00:38:19 -0400 Subject: [PATCH] Fix binary stdin/stdout io in Windows Make --font-file accept "-" to mean stdin, and have it work in Windows too! --- configure.ac | 2 +- util/common.hh | 5 ++++ util/options.cc | 64 ++++++++++++++++++++++++++++++++++++++++--------- util/options.hh | 10 ++++++-- 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 82451814d..e1b6bf8d9 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) # Functions and headers AC_CHECK_FUNCS(mprotect sysconf getpagesize mmap) -AC_CHECK_HEADERS(unistd.h sys/mman.h) +AC_CHECK_HEADERS(unistd.h sys/mman.h io.h) # Compiler flags AC_CANONICAL_HOST diff --git a/util/common.hh b/util/common.hh index 015dbf4f1..1ce61af56 100644 --- a/util/common.hh +++ b/util/common.hh @@ -40,6 +40,11 @@ #include #include #include +#include +#if HAVE_IO_H +#include /* for _setmode() under Windows */ +#endif + #include #include diff --git a/util/options.cc b/util/options.cc index 561b6aa7e..b1fb4ce2f 100644 --- a/util/options.cc +++ b/util/options.cc @@ -424,23 +424,66 @@ font_options_t::get_font (void) const /* Create the blob */ { - const char *font_data; - unsigned int len; + char *font_data; + unsigned int len = 0; hb_destroy_func_t destroy; void *user_data; hb_memory_mode_t mm; + /* This is a hell of a lot of code for just reading a file! */ if (!font_file) fail (TRUE, "No font file set"); - GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL); - if (!mf) - fail (FALSE, "Failed opening font file `%s'", g_filename_display_name (font_file)); - font_data = g_mapped_file_get_contents (mf); - len = g_mapped_file_get_length (mf); - destroy = (hb_destroy_func_t) g_mapped_file_unref; - user_data = (void *) mf; - mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE; + if (0 == strcmp (font_file, "-")) { + /* read it */ + GString *gs = g_string_new (NULL); + char buf[BUFSIZ]; +#if HAVE_IO_H + _setmode (fileno (stdin), O_BINARY); +#endif + while (!feof (stdin)) { + size_t ret = fread (buf, 1, sizeof (buf), stdin); + if (ferror (stdin)) + fail (FALSE, "Failed reading font from standard input: %s", + strerror (errno)); + g_string_append_len (gs, buf, ret); + } + len = gs->len; + font_data = g_string_free (gs, FALSE); + user_data = font_data; + destroy = (hb_destroy_func_t) g_free; + mm = HB_MEMORY_MODE_WRITABLE; + } else { + GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL); + if (mf) { + font_data = g_mapped_file_get_contents (mf); + len = g_mapped_file_get_length (mf); + if (len) { + destroy = (hb_destroy_func_t) g_mapped_file_unref; + user_data = (void *) mf; + mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE; + } else + g_mapped_file_unref (mf); + } + if (!len) { + /* GMappedFile is buggy, it doesn't fail if file isn't regular. + * Try reading. + * https://bugzilla.gnome.org/show_bug.cgi?id=659212 */ + GError *error = NULL; + gsize l; + if (g_file_get_contents (font_file, &font_data, &l, &error)) { + len = l; + destroy = (hb_destroy_func_t) g_free; + user_data = (void *) font_data; + mm = HB_MEMORY_MODE_WRITABLE; + } else { + fail (FALSE, "Failed reading font file `%s': %s", + g_filename_display_name (font_file), + error->message); + //g_error_free (error); + } + } + } blob = hb_blob_create (font_data, len, mm, user_data, destroy); } @@ -476,7 +519,6 @@ text_options_t::get_line (unsigned int *len) fail (FALSE, "Failed opening text file `%s'", g_filename_display_name (text_file)); text = g_mapped_file_get_contents (mf); text_len = g_mapped_file_get_length (mf); - printf ("%d\n", text_len); } if (text_len == (unsigned int) -1) diff --git a/util/options.hh b/util/options.hh index b21387206..623e25a9d 100644 --- a/util/options.hh +++ b/util/options.hh @@ -208,7 +208,6 @@ struct text_options_t : option_group_t mutable unsigned int text_len; }; - struct output_options_t : option_group_t { output_options_t (option_parser_t *parser) { @@ -243,7 +242,14 @@ struct output_options_t : option_group_t if (fp) return fp; - fp = output_file ? fopen (output_file, "wb") : stdout; + if (output_file) + fp = fopen (output_file, "wb"); + else { +#if HAVE_IO_H + _setmode (fileno (stdout), O_BINARY); +#endif + fp = stdout; + } if (!fp) fail (FALSE, "Cannot open output file `%s': %s", g_filename_display_name (output_file), strerror (errno));