From 58912f68c2489bcee787599837447e0d64dfd61a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= <debian@jff-webhosting.net>
Date: Wed, 24 May 2017 21:03:56 +0200
Subject: New upstream version 1.0.27

---
 frontend/Makefile.am |  12 ++--
 frontend/Makefile.in |  86 +++++++++++++++++---------
 frontend/saned.c     | 169 ++++++++++++++++++++++++++++++++++++---------------
 frontend/scanimage.c | 100 ++++++++++++++++++++++++++----
 frontend/sicc.c      |  67 ++++++++++++++++++++
 frontend/sicc.h      |  19 ++++++
 frontend/stiff.c     |  99 ++++++++----------------------
 7 files changed, 381 insertions(+), 171 deletions(-)
 create mode 100644 frontend/sicc.c
 create mode 100644 frontend/sicc.h

(limited to 'frontend')

diff --git a/frontend/Makefile.am b/frontend/Makefile.am
index 23061b3..525953f 100644
--- a/frontend/Makefile.am
+++ b/frontend/Makefile.am
@@ -14,21 +14,21 @@ else
 EXTRA_PROGRAMS += saned
 endif
 
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
+AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
 
-scanimage_SOURCES = scanimage.c stiff.c stiff.h
+scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
 scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
-             ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@
+                  $(PNG_LIBS) $(JPEG_LIBS)
 
 saned_SOURCES = saned.c
 saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
-             ../lib/libfelib.la @SYSLOG_LIBS@ @SYSTEMD_LIBS@
+              $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS)
 
 test_SOURCES = test.c
-test_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+test_LDADD = ../lib/liblib.la ../backend/libsane.la
 
 tstbackend_SOURCES = tstbackend.c
-tstbackend_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la
 
 clean-local:
 	rm -f test tstbackend
diff --git a/frontend/Makefile.in b/frontend/Makefile.in
index 2e36e0e..9ea467f 100644
--- a/frontend/Makefile.in
+++ b/frontend/Makefile.in
@@ -86,11 +86,16 @@ subdir = frontend
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ltoptions.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/byteorder.m4 \
-	$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/configure.in
+	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \
+	$(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -102,24 +107,25 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
 PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
 am_saned_OBJECTS = saned.$(OBJEXT)
 saned_OBJECTS = $(am_saned_OBJECTS)
+am__DEPENDENCIES_1 =
 saned_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \
-	../lib/liblib.la ../lib/libfelib.la
+	../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
-am_scanimage_OBJECTS = scanimage.$(OBJEXT) stiff.$(OBJEXT)
+am_scanimage_OBJECTS = scanimage.$(OBJEXT) sicc.$(OBJEXT) \
+	stiff.$(OBJEXT)
 scanimage_OBJECTS = $(am_scanimage_OBJECTS)
 scanimage_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \
-	../lib/liblib.la ../lib/libfelib.la
+	../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am_test_OBJECTS = test.$(OBJEXT)
 test_OBJECTS = $(am_test_OBJECTS)
-test_DEPENDENCIES = ../lib/liblib.la ../lib/libfelib.la \
-	../backend/libsane.la
+test_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la
 am_tstbackend_OBJECTS = tstbackend.$(OBJEXT)
 tstbackend_OBJECTS = $(am_tstbackend_OBJECTS)
-tstbackend_DEPENDENCIES = ../lib/liblib.la ../lib/libfelib.la \
-	../backend/libsane.la
+tstbackend_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -186,7 +192,11 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
 ALLOCA = @ALLOCA@
 AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \
+	-I$(top_srcdir)/include
 AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_LDFLAGS = @AM_LDFLAGS@
 AR = @AR@
 AS = @AS@
 AUTOCONF = @AUTOCONF@
@@ -207,7 +217,7 @@ CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
-DISTCLEAN_FILES = @DISTCLEAN_FILES@
+DLH = @DLH@
 DLLTOOL = @DLLTOOL@
 DL_LIBS = @DL_LIBS@
 DSYMUTIL = @DSYMUTIL@
@@ -220,34 +230,42 @@ ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FIG2DEV = @FIG2DEV@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
 GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@
 GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@
 GPHOTO2_LIBS = @GPHOTO2_LIBS@
 GREP = @GREP@
+GS = @GS@
 HAVE_GPHOTO2 = @HAVE_GPHOTO2@
 IEEE1284_LIBS = @IEEE1284_LIBS@
-INCLUDES = @INCLUDES@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_LOCKPATH = @INSTALL_LOCKPATH@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
 JPEG_LIBS = @JPEG_LIBS@
 LATEX = @LATEX@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
-LIBUSB_1_0_CFLAGS = @LIBUSB_1_0_CFLAGS@
-LIBUSB_1_0_LIBS = @LIBUSB_1_0_LIBS@
 LIBV4L_CFLAGS = @LIBV4L_CFLAGS@
 LIBV4L_LIBS = @LIBV4L_LIBS@
-LINKER_RPATH = @LINKER_RPATH@
 LIPO = @LIPO@
 LN_S = @LN_S@
 LOCKPATH_GROUP = @LOCKPATH_GROUP@
+LTALLOCA = @LTALLOCA@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
 MAINT = @MAINT@
 MAKEINDEX = @MAKEINDEX@
@@ -256,10 +274,10 @@ MANIFEST_TOOL = @MANIFEST_TOOL@
 MATH_LIB = @MATH_LIB@
 MKDIR_P = @MKDIR_P@
 MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
 NM = @NM@
 NMEDIT = @NMEDIT@
-NUMBER_VERSION = @NUMBER_VERSION@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
 OTOOL = @OTOOL@
@@ -272,10 +290,13 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PNG_LIBS = @PNG_LIBS@
+POSUB = @POSUB@
+PPMTOGIF = @PPMTOGIF@
 PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@
 PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -297,12 +318,16 @@ SYSLOG_LIBS = @SYSLOG_LIBS@
 SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
 SYSTEMD_LIBS = @SYSTEMD_LIBS@
 TIFF_LIBS = @TIFF_LIBS@
+USB_CFLAGS = @USB_CFLAGS@
 USB_LIBS = @USB_LIBS@
+USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 V_MAJOR = @V_MAJOR@
 V_MINOR = @V_MINOR@
 V_REV = @V_REV@
 XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -358,19 +383,18 @@ target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
-scanimage_SOURCES = scanimage.c stiff.c stiff.h
+scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
 scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
-             ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@
+                  $(PNG_LIBS) $(JPEG_LIBS)
 
 saned_SOURCES = saned.c
 saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
-             ../lib/libfelib.la @SYSLOG_LIBS@ @SYSTEMD_LIBS@
+              $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS)
 
 test_SOURCES = test.c
-test_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+test_LDADD = ../lib/liblib.la ../backend/libsane.la
 tstbackend_SOURCES = tstbackend.c
-tstbackend_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la
 all: all-am
 
 .SUFFIXES:
@@ -528,27 +552,31 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saned.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanimage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sicc.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stiff.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tstbackend.Po@am__quote@
 
 .c.o:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
 
 .c.obj:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
 .c.lo:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
diff --git a/frontend/saned.c b/frontend/saned.c
index 108512d..3bb99bb 100644
--- a/frontend/saned.c
+++ b/frontend/saned.c
@@ -82,6 +82,8 @@
 #include <pwd.h>
 #include <grp.h>
 
+#include "lgetopt.h"
+
 #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
 # include <sys/poll.h>
 #else
@@ -196,16 +198,19 @@ static AvahiEntryGroup *avahi_group = NULL;
 #endif
 
 #ifdef ENABLE_IPV6
-# define SANE_IN6_IS_ADDR_LOOPBACK(a) \
+# ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
         (((const uint32_t *) (a))[0] == 0                                   \
          && ((const uint32_t *) (a))[1] == 0                                \
          && ((const uint32_t *) (a))[2] == 0                                \
          && ((const uint32_t *) (a))[3] == htonl (1)) 
-
-#define SANE_IN6_IS_ADDR_V4MAPPED(a) \
+# endif
+# ifndef IN6_IS_ADDR_V4MAPPED
+# define IN6_IS_ADDR_V4MAPPED(a) \
 ((((const uint32_t *) (a))[0] == 0)                                 \
  && (((const uint32_t *) (a))[1] == 0)                              \
  && (((const uint32_t *) (a))[2] == htonl (0xffff))) 
+# endif
 #endif /* ENABLE_IPV6 */
 
 #ifndef MAXHOSTNAMELEN
@@ -247,6 +252,7 @@ static int num_handles;
 static int debug;
 static int run_mode;
 static Handle *handle;
+static char *bind_addr;
 static union
 {
   int w;
@@ -786,7 +792,7 @@ check_host (int fd)
 #ifdef ENABLE_IPV6
   sin6 = &remote_address.sin6;
 
-  if (SANE_IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr))
+  if (IN6_IS_ADDR_V4MAPPED ((struct in6_addr *)sin6->sin6_addr.s6_addr))
     {
       DBG (DBG_DBG, "check_host: detected an IPv4-mapped address\n");
       remote_ipv4 = remote_ip + 7;
@@ -843,7 +849,7 @@ check_host (int fd)
 	break;
 #ifdef ENABLE_IPV6
       case AF_INET6:
-	if (SANE_IN6_IS_ADDR_LOOPBACK (sin6->sin6_addr.s6_addr))
+	if (IN6_IS_ADDR_LOOPBACK ((struct in6_addr *)sin6->sin6_addr.s6_addr))
 	  {
 	    DBG (DBG_MSG,
 		 "check_host: remote host is IN6_LOOPBACK: access granted\n");
@@ -1428,7 +1434,7 @@ start_scan (Wire * w, int h, SANE_Start_Reply * reply)
   SANE_Handle be_handle;
   int fd, len;
   in_port_t data_port;
-  int ret;
+  int ret = -1;
 
   be_handle = handle[h].handle;
 
@@ -1986,6 +1992,38 @@ process_request (Wire * w)
 	    return 1;
 	  }
 
+        /* Addresses CVE-2017-6318 (#315576, Debian BTS #853804) */
+        /* This is done here (rather than in sanei/sanei_wire.c where
+         * it should be done) to minimize scope of impact and amount
+         * of code change.
+         */
+        if (w->direction == WIRE_DECODE
+            && req.value_type == SANE_TYPE_STRING
+            && req.action     == SANE_ACTION_GET_VALUE)
+          {
+            if (req.value)
+              {
+                /* FIXME: If req.value contains embedded NUL
+                 *        characters, this is wrong but we do not have
+                 *        access to the amount of memory allocated in
+                 *        sanei/sanei_wire.c at this point.
+                 */
+                w->allocated_memory -= (1 + strlen (req.value));
+                free (req.value);
+              }
+            req.value = malloc (req.value_size);
+            if (!req.value)
+              {
+                w->status = ENOMEM;
+                DBG (DBG_ERR,
+                     "process_request: (control_option) "
+                     "h=%d (%s)\n", req.handle, strerror (w->status));
+                return 1;
+              }
+            memset (req.value, 0, req.value_size);
+            w->allocated_memory += req.value_size;
+          }
+
 	can_authorize = 1;
 
 	memset (&reply, 0, sizeof (reply));	/* avoid leaking bits */
@@ -2807,13 +2845,13 @@ do_bindings (int *nfds, struct pollfd **fds)
   hints.ai_flags = AI_PASSIVE;
   hints.ai_socktype = SOCK_STREAM;
 
-  err = getaddrinfo (NULL, SANED_SERVICE_NAME, &hints, &res);
+  err = getaddrinfo (bind_addr, SANED_SERVICE_NAME, &hints, &res);
   if (err)
     {
       DBG (DBG_WARN, "do_bindings: \" %s \" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
       DBG (DBG_WARN, "do_bindings:      %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
       DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
-      err = getaddrinfo (NULL, SANED_SERVICE_PORT_S, &hints, &res);
+      err = getaddrinfo (bind_addr, SANED_SERVICE_PORT_S, &hints, &res);
       if (err)
 	{
 	  DBG (DBG_ERR, "do_bindings: getaddrinfo() failed even with numeric port: %s\n", gai_strerror (err));
@@ -2891,7 +2929,10 @@ do_bindings (int *nfds, struct pollfd **fds)
   memset (&sin, 0, sizeof (sin));
 
   sin.sin_family = AF_INET;
-  sin.sin_addr.s_addr = INADDR_ANY;
+  if(bind_addr)
+    sin.sin_addr.s_addr = inet_addr(bind_addr);
+  else
+    sin.sin_addr.s_addr = INADDR_ANY;
   sin.sin_port = port;
 
   DBG (DBG_DBG, "do_bindings: socket ()\n");
@@ -2923,7 +2964,7 @@ do_bindings (int *nfds, struct pollfd **fds)
 
 
 static void
-run_standalone (int argc, char **argv)
+run_standalone (char *user)
 {
   struct pollfd *fds = NULL;
   struct pollfd *fdp = NULL;
@@ -2944,13 +2985,13 @@ run_standalone (int argc, char **argv)
 
   if (run_mode != SANED_RUN_DEBUG)
     {
-      if (argc > 2)
+      if (user)
 	{
-	  pwent = getpwnam(argv[2]);
+	  pwent = getpwnam(user);
 
 	  if (pwent == NULL)
 	    {
-	      DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", argv[2]);
+	      DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", user);
 	      bail_out (1);
 	    }
 
@@ -2981,7 +3022,7 @@ run_standalone (int argc, char **argv)
 
               while (grp->gr_mem[i])
 		{
-                  if (strcmp(grp->gr_mem[i], argv[2]) == 0)
+                  if (strcmp(grp->gr_mem[i], user) == 0)
                     {
                       int need_to_add = 1, j;
 
@@ -3172,7 +3213,7 @@ run_standalone (int argc, char **argv)
 
 
 static void
-run_inetd (int argc, char **argv)
+run_inetd (char __sane_unused__ *sock)
 {
   
   int fd = -1;
@@ -3238,18 +3279,13 @@ run_inetd (int argc, char **argv)
 
       close (dave_null);
     }
-#ifndef HAVE_OS2_H
-  /* Unused in this function */
-  argc = argc;
-  argv = argv;
-
-#else
+#ifdef HAVE_OS2_H
   /* under OS/2, the socket handle is passed as argument on the command
      line; the socket handle is relative to IBM TCP/IP, so a call
      to impsockethandle() is required to add it to the EMX runtime */
-  if (argc == 2)
+  if (sock)
     {
-      fd = _impsockhandle (atoi (argv[1]), 0);
+      fd = _impsockhandle (atoi (sock), 0);
       if (fd == -1)
 	perror ("impsockhandle");
     }
@@ -3258,11 +3294,44 @@ run_inetd (int argc, char **argv)
   handle_connection(fd);
 }
 
+static void usage(char *me, int err)
+{
+  fprintf (stderr,
+       "Usage: %s [OPTIONS]\n\n"
+       " Options:\n\n"
+       "  -a, --alone[=user]	run standalone and fork in background as `user'\n"
+       "  -d, --debug[=level]	run foreground with output to stdout\n"
+       "			and debug level `level' (default is 2)\n"
+       "  -s, --syslog[=level]	run foreground with output to syslog\n"
+       "			and debug level `level' (default is 2)\n"
+       "  -b, --bind=addr	bind address `addr'\n"
+       "  -h, --help		show this help message and exit\n", me);
+
+  exit(err);
+}
+
+static int debug;
+
+static struct option long_options[] =
+{
+/* These options set a flag. */
+  {"help",	no_argument,		0, 'h'},
+  {"alone",	optional_argument,	0, 'a'},
+  {"debug",	optional_argument,	0, 'd'},
+  {"syslog",	optional_argument,	0, 's'},
+  {"bind",	required_argument,	0, 'b'},
+  {0,		0,			0,  0 }
+};
 
 int
 main (int argc, char *argv[])
 {
   char options[64] = "";
+  char *user = NULL;
+  char *sock = NULL;
+  int c;
+  int long_index = 0;
+
   debug = DBG_WARN;
 
   prog_name = strrchr (argv[0], '/');
@@ -3274,34 +3343,30 @@ main (int argc, char *argv[])
   numchildren = 0;
   run_mode = SANED_RUN_INETD;
 
-  if (argc >= 2)
+  while((c = getopt_long(argc, argv,"ha::d::s::b:", long_options, &long_index )) != -1)
     {
-      if (strncmp (argv[1], "-a", 2) == 0)
+      switch(c) {
+      case 'a':
 	run_mode = SANED_RUN_ALONE;
-      else if (strncmp (argv[1], "-d", 2) == 0)
-	{
-	  run_mode = SANED_RUN_DEBUG;
-	  log_to_syslog = SANE_FALSE;
-	}
-      else if (strncmp (argv[1], "-s", 2) == 0)
+	user = optarg;
+	break;
+      case 'd':
+	log_to_syslog = SANE_FALSE;
+      case 's':
 	run_mode = SANED_RUN_DEBUG;
-      else
-        {
-          printf ("Usage: saned [ -a [ username ] | -d [ n ] | -s [ n ] ] | -h\n");
-          if ((strncmp (argv[1], "-h", 2) == 0) ||
-               (strncmp (argv[1], "--help", 6) == 0))
-            exit (EXIT_SUCCESS);
-          else
-            exit (EXIT_FAILURE);
-        }
-    }
-
-  if (run_mode == SANED_RUN_DEBUG)
-    {
-      if (argv[1][2])
-	debug = atoi (argv[1] + 2);
-
-      DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
+	if(optarg)
+	  debug = atoi(optarg);
+	break;
+      case 'b':
+	bind_addr = optarg;
+	break;
+      case 'h':
+	usage(argv[0], EXIT_SUCCESS);
+	break;
+      default:
+	usage(argv[0], EXIT_FAILURE);
+	break;
+      }
     }
 
   if (log_to_syslog)
@@ -3342,11 +3407,15 @@ main (int argc, char *argv[])
 
   if ((run_mode == SANED_RUN_ALONE) || (run_mode == SANED_RUN_DEBUG))
     {
-      run_standalone(argc, argv);
+      run_standalone(user);
     }
   else
     {
-      run_inetd(argc, argv);
+#ifdef HAVE_OS2_H
+      if (argc == 2)
+	sock = argv[1];
+#endif
+      run_inetd(sock);
     }
 
   DBG (DBG_WARN, "saned exiting\n");
diff --git a/frontend/scanimage.c b/frontend/scanimage.c
index 7f7c1f0..fe02750 100644
--- a/frontend/scanimage.c
+++ b/frontend/scanimage.c
@@ -56,6 +56,7 @@
 #include "../include/sane/sanei.h"
 #include "../include/sane/saneopts.h"
 
+#include "sicc.h"
 #include "stiff.h"
 
 #include "../include/md5.h"
@@ -322,7 +323,7 @@ auth_callback (SANE_String_Const resource,
     }
 }
 
-static RETSIGTYPE
+static void
 sighandler (int signum)
 {
   static SANE_Bool first_time = SANE_TRUE;
@@ -1165,9 +1166,14 @@ write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp
 
 #ifdef HAVE_LIBPNG
 static void
-write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
+write_png_header (SANE_Frame format, int width, int height, int depth, int dpi, const char * icc_profile, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
 {
   int color_type;
+  /* PNG does not have imperial reference units, so we must convert to metric. */
+  /* There are nominally 39.3700787401575 inches in a meter. */
+  const double pixels_per_meter = dpi * 39.3700787401575;
+  size_t icc_size = 0;
+  void *icc_buffer;
 
   *png_ptr = png_create_write_struct
        (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
@@ -1200,13 +1206,47 @@ write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp
     depth, color_type, PNG_INTERLACE_NONE,
     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
 
+  png_set_pHYs(*png_ptr, *info_ptr,
+    pixels_per_meter, pixels_per_meter,
+    PNG_RESOLUTION_METER);
+
+  if (icc_profile)
+    {
+      icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
+      if (icc_size > 0)
+        {
+	  /* libpng will abort if the profile and image colour spaces do not match*/
+	  /* The data colour space field is at bytes 16 to 20 in an ICC profile */
+	  /* see: ICC.1:2010 ยง 7.2.6 */
+	  int is_gray_profile = strncmp((char *) icc_buffer + 16, "GRAY", 4) == 0;
+	  int is_rgb_profile = strncmp((char *) icc_buffer + 16, "RGB ", 4) == 0;
+	  if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) ||
+	      (is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB))
+	    {
+	      png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
+	    }
+	  else
+	    {
+	      if (is_gray_profile)
+	        {
+		  fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n");
+	        }
+	      if (is_rgb_profile)
+	        {
+		  fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n");
+		}
+	    }
+	  free(icc_buffer);
+	}
+    }
+
   png_write_info(*png_ptr, *info_ptr);
 }
 #endif
 
 #ifdef HAVE_LIBJPEG
 static void
-write_jpeg_header (SANE_Frame format, int width, int height, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr)
+write_jpeg_header (SANE_Frame format, int width, int height, int dpi, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr)
 {
   cinfo->err = jpeg_std_error(jerr);
   jpeg_create_compress(cinfo);
@@ -1231,6 +1271,11 @@ write_jpeg_header (SANE_Frame format, int width, int height, FILE *ofp, struct j
     }
 
   jpeg_set_defaults(cinfo);
+  /* jpeg_set_defaults overrides density, be careful. */
+  cinfo->density_unit = 1;   /* Inches */
+  cinfo->X_density = cinfo->Y_density = dpi;
+  cinfo->write_JFIF_header = TRUE;
+
   jpeg_set_quality(cinfo, 75, TRUE);
   jpeg_start_compress(cinfo, TRUE);
 }
@@ -1379,13 +1424,15 @@ scan_it (FILE *ofp)
 #ifdef HAVE_LIBPNG
 		  case OUTPUT_PNG:
 		    write_png_header (parm.format, parm.pixels_per_line,
-				      parm.lines, parm.depth, ofp, &png_ptr, &info_ptr);
+				      parm.lines, parm.depth, resolution_value,
+				      icc_profile, ofp, &png_ptr, &info_ptr);
 		    break;
 #endif
 #ifdef HAVE_LIBJPEG
 		  case OUTPUT_JPEG:
 		    write_jpeg_header (parm.format, parm.pixels_per_line,
-				      parm.lines, ofp, &cinfo, &jerr);
+				       parm.lines, resolution_value,
+				       ofp, &cinfo, &jerr);
 		    break;
 #endif
 		  }
@@ -1529,6 +1576,21 @@ scan_it (FILE *ofp)
 			  for(j = 0; j < parm.bytes_per_line; j++)
 			    pngbuf[j] = ~pngbuf[j];
 			}
+#ifndef WORDS_BIGENDIAN
+                      /* SANE is endian-native, PNG is big-endian, */
+                      /* see: https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order */
+                      if (parm.depth == 16)
+                        {
+                          int j;
+                          for (j = 0; j < parm.bytes_per_line; j += 2)
+                            {
+                              SANE_Byte LSB;
+                              LSB = pngbuf[j];
+                              pngbuf[j] = pngbuf[j + 1];
+                              pngbuf[j + 1] = LSB;
+                            }
+                        }
+#endif
 		      png_write_row(png_ptr, pngbuf);
 		      i += parm.bytes_per_line - pngrow;
 		      left -= parm.bytes_per_line - pngrow;
@@ -1635,13 +1697,15 @@ scan_it (FILE *ofp)
 #ifdef HAVE_LIBPNG
       case OUTPUT_PNG:
 	write_png_header (parm.format, parm.pixels_per_line,
-                          image.height, parm.depth, ofp, &png_ptr, &info_ptr);
+			  image.height, parm.depth, resolution_value,
+			  icc_profile, ofp, &png_ptr, &info_ptr);
       break;
 #endif
 #ifdef HAVE_LIBJPEG
       case OUTPUT_JPEG:
 	write_jpeg_header (parm.format, parm.pixels_per_line,
-	parm.lines, ofp, &cinfo, &jerr);
+			   parm.lines, resolution_value,
+			   ofp, &cinfo, &jerr);
       break;
 #endif
       }
@@ -2474,9 +2538,16 @@ List of available devices:", prog_name);
         ofp = stdout;
 
       if (batch)
-	fprintf (stderr,
-		 "Scanning %d pages, incrementing by %d, numbering from %d\n",
-		 batch_count, batch_increment, batch_start_at);
+	{
+	  fputs("Scanning ", stderr);
+	  if (batch_count == BATCH_COUNT_UNLIMITED)
+	    fputs("infinity", stderr);
+	  else
+	    fprintf(stderr, "%d", batch_count);
+	  fprintf (stderr,
+		   " page%s, incrementing by %d, numbering from %d\n",
+		   batch_count == 1 ? "" : "s", batch_increment, batch_start_at);
+	}
 
       else if(isatty(fileno(ofp))){
 	fprintf (stderr,"%s: output is not a file, exiting\n", prog_name);
@@ -2509,8 +2580,6 @@ List of available devices:", prog_name);
 
 		  if (readbuf2 == NULL)
 		    {
-		      fprintf (stderr, "Batch terminated, %d pages scanned\n",
-			       (n - batch_increment));
 		      if (ofp)
 			{
 			  fclose (ofp);
@@ -2612,6 +2681,13 @@ List of available devices:", prog_name);
 	      && (batch_count == BATCH_COUNT_UNLIMITED || --batch_count))
 	     && SANE_STATUS_GOOD == status);
 
+      if (batch)
+	{
+	  int num_pgs = (n - batch_start_at) / batch_increment;
+	  fprintf (stderr, "Batch terminated, %d page%s scanned\n",
+		   num_pgs, num_pgs == 1 ? "" : "s");
+	}
+
       if (batch
 	  && SANE_STATUS_NO_DOCS == status
 	  && (batch_count == BATCH_COUNT_UNLIMITED)
diff --git a/frontend/sicc.c b/frontend/sicc.c
new file mode 100644
index 0000000..c93e5c3
--- /dev/null
+++ b/frontend/sicc.c
@@ -0,0 +1,67 @@
+/* Load an ICC profile for embedding in an output file
+   Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "../include/sane/config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+void *
+sanei_load_icc_profile (const char *path, size_t *size)
+{
+  FILE *fd = NULL;
+  size_t stated_size = 0;
+  void *profile = NULL;
+  struct stat s;
+
+  fd = fopen(path, "r");
+
+  if (!fd)
+  {
+    fprintf(stderr, "Could not open ICC profile %s\n", path);
+  }
+  else
+  {
+    fstat(fileno(fd), &s);
+    stated_size = 16777216 * fgetc(fd) + 65536 * fgetc(fd) + 256 * fgetc(fd) + fgetc(fd);
+    rewind(fd);
+
+    if (stated_size > (size_t) s.st_size)
+    {
+      fprintf(stderr, "Ignoring ICC profile because file %s is shorter than the profile\n", path);
+    }
+    else
+    {
+      profile = malloc(stated_size);
+
+      if (fread(profile, stated_size, 1, fd) != 1)
+      {
+        fprintf(stderr, "Error reading ICC profile %s\n", path);
+        free(profile);
+      }
+      else
+      {
+        fclose(fd);
+        *size = stated_size;
+        return profile;
+      }
+    }
+    fclose(fd);
+  }
+  return NULL;
+}
diff --git a/frontend/sicc.h b/frontend/sicc.h
new file mode 100644
index 0000000..5c225da
--- /dev/null
+++ b/frontend/sicc.h
@@ -0,0 +1,19 @@
+/* Load an ICC profile for embedding in an output file
+   Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+void *
+sanei_load_icc_profile (const char *path, size_t *size);
diff --git a/frontend/stiff.c b/frontend/stiff.c
index 01d845b..c9153e5 100644
--- a/frontend/stiff.c
+++ b/frontend/stiff.c
@@ -1,6 +1,7 @@
 /* Create SANE/tiff headers TIFF interfacing routines for SANE
    Copyright (C) 2000 Peter Kirchgessner
    Copyright (C) 2002 Oliver Rauch: added tiff ICC profile
+   Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -20,6 +21,7 @@
    2000-11-19, PK: Color TIFF-header: write 3 values for bits per sample
    2001-12-16, PK: Write fill order tag for b/w-images
    2002-08-27, OR: Added tiff tag for ICC profile
+   2017-04-16, AMH: Separate ICC profile loading into a separate file
 */
 #ifdef _AIX
 # include "../include/lalloca.h"	/* MUST come first for AIX! */
@@ -31,6 +33,7 @@
 #include "../include/sane/config.h"
 #include "../include/sane/sane.h"
 
+#include "sicc.h"
 #include "stiff.h"
 
 typedef struct {
@@ -269,22 +272,12 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
     int strip_bytecount;
     int ntags;
     int motorola, bps, maxsamplevalue;
-    FILE *icc_file = 0;
-    int icc_len = -1;
+    void *icc_buffer = NULL;
+    size_t icc_size = 0;
 
     if (icc_profile)
     {
-      icc_file = fopen(icc_profile, "r");
-
-      if (!icc_file)
-      {
-        fprintf(stderr, "Could not open ICC profile %s\n", icc_profile);
-      }
-      else
-      {
-        icc_len = 16777216 * fgetc(icc_file) + 65536 * fgetc(icc_file) + 256 * fgetc(icc_file) + fgetc(icc_file);
-        rewind(icc_file);
-      }
+      icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
     }
 
     ifd = create_ifd ();
@@ -302,10 +295,10 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
         data_size += 2*4 + 2*4;
     }
 
-    if (icc_len > 0) /* if icc profile exists add memory for tag */
+    if (icc_size > 0) /* if icc profile exists add memory for tag */
     {
         ntags += 1;
-        data_size += icc_len;
+        data_size += icc_size;
     }
 
     ifd_size = 2 + ntags*12 + 4;
@@ -355,10 +348,10 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
         add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
     }
 
-    if (icc_len > 0) /* add ICC-profile TAG */
+    if (icc_size > 0) /* add ICC-profile TAG */
     {
-      add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
-      data_offset += icc_len;
+      add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
+      data_offset += icc_size;
     }
 
     /* I prefer motorola format. Its human readable. But for 16 bit, */
@@ -383,33 +376,16 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
         write_i4 (fptr, 1, motorola);
     }
 
-    /* Write ICC profile */
-    if (icc_len > 0)
+    if (icc_size > 0)
     {
-      int i;
-      for (i=0; i<icc_len; i++)
-      {
-        if (!feof(icc_file))
-        {
-          fputc(fgetc(icc_file), fptr);
-        }
-        else
-        {
-          fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
-          break;
-        }
-      }
+      fwrite(icc_buffer, icc_size, 1, fptr);
     }
 
-    if (icc_file)
-    {
-      fclose(icc_file);
-    }
+    free(icc_buffer);
 
     free_ifd (ifd);
 }
 
-
 static void
 write_tiff_color_header (FILE *fptr, int width, int height, int depth,
                          int resolution, const char *icc_profile)
@@ -419,22 +395,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
     int strip_bytecount;
     int ntags;
     int motorola, bps, maxsamplevalue;
-    FILE *icc_file = 0;
-    int icc_len = -1;
+    void *icc_buffer = NULL;
+    size_t icc_size = 0;
 
     if (icc_profile)
     {
-      icc_file = fopen(icc_profile, "r");
-
-      if (!icc_file)
-      {
-        fprintf(stderr, "Could not open ICC profile %s\n", icc_profile);
-      }
-      else
-      {
-        icc_len = 16777216 * fgetc(icc_file) + 65536 * fgetc(icc_file) + 256 * fgetc(icc_file) + fgetc(icc_file);
-        rewind(icc_file);
-      }
+      icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
     }
 
 
@@ -454,10 +420,10 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
         data_size += 2*4 + 2*4;
     }
 
-    if (icc_len > 0) /* if icc profile exists add memory for tag */
+    if (icc_size > 0) /* if icc profile exists add memory for tag */
     {
         ntags += 1;
-        data_size += icc_len;
+        data_size += icc_size;
     }
 
 
@@ -513,10 +479,10 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
         add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
     }
 
-    if (icc_len > 0) /* add ICC-profile TAG */
+    if (icc_size > 0) /* add ICC-profile TAG */
     {
-      add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
-      data_offset += icc_len;
+      add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
+      data_offset += icc_size;
     }
 
 
@@ -558,27 +524,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
     }
 
     /* Write ICC profile */
-    if (icc_len > 0)
+    if (icc_size > 0)
     {
-      int i;
-      for (i=0; i<icc_len; i++)
-      {
-        if (!feof(icc_file))
-        {
-          fputc(fgetc(icc_file), fptr);
-        }
-        else
-        {
-          fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
-          break;
-        }
-      }
+      fwrite(icc_buffer, icc_size, 1, fptr);
     }
 
-    if (icc_file)
-    {
-      fclose(icc_file);
-    }
+    free(icc_buffer);
 
     free_ifd (ifd);
 }
-- 
cgit v1.2.3