cupsPrintFile() has no streaming equivalent?

mike dizaemon at hotmail.com
Fri Feb 23 13:44:59 PST 2007


> > > If you look at the cupsDoFileRequest code in cups/request.c,
> > > you'll see how to use the lower-level HTTP and IPP APIs to stream
> > > your content to the CUPS server.

[snip]

> > if there was some type of chunked/segmented file transfer method
> > where set blocks of the file are transferred at a time, then perhaps
> > the streaming method would work.  is there such support in cups?

[snip]

> so it would appear that transmitting the data as a sequence of chunks is
> possible, according to the RFC.  i'm still reading, but i thought i'd
> mention it in case anyone has any insight into how CUPS implements
> chunked IPP_PRINT_JOB requests.

after finally figuring out that the http code automatically does chunked
transfer encoding when HTTP_FIELD_TRANSFER_ENCODING is set to "chunked",
i've got a diff against cups-1.2 that implements cupsPrintStream.
please test it out for me and let me know what you think!

-mike

--- snip --- snip --- snip ---
Index: cups/request.c
===================================================================
--- cups/request.c	(revision 6305)
+++ cups/request.c	(working copy)
@@ -36,6 +36,7 @@

 #include "globals.h"
 #include "debug.h"
+#include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -48,34 +49,33 @@


 /*
- * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ * 'cupsDoStreamRequest()' - Do a stream request with a file.
  *
  * This function sends the IPP request to the specified server, retrying
  * and authenticating as necessary.  The request is freed with ippDelete()
  * after receiving a valid IPP response.
  */

-ipp_t *					/* O - Response data */
-cupsDoFileRequest(http_t     *http,	/* I - HTTP connection to server */
-                  ipp_t      *request,	/* I - IPP request */
-                  const char *resource,	/* I - HTTP resource for POST */
-		  const char *filename)	/* I - File to send or NULL for none */
+ipp_t *                                         /* O - Response data */
+cupsDoStreamRequest(http_t           *http,     /* I - HTTP connection to server */
+                    ipp_t            *request,  /* I - IPP request */
+                    const char       *resource, /* I - HTTP resource for POST */
+                    cups_stream_cb_t fpread,    /* I - function pointer for read */
+                    void             *arg)      /* I - arbitrary arg to pass to fp */
 {
   ipp_t		*response;		/* IPP response data */
   size_t	length;			/* Content-Length value */
   http_status_t	status;			/* Status of HTTP request */
   int		got_status;		/* Did we get the status? */
   ipp_state_t	state;			/* State of IPP processing */
-  FILE		*file;			/* File to send */
-  struct stat	fileinfo;		/* File information */
   int		bytes;			/* Number of bytes read/written */
   char		buffer[32768];		/* Output buffer */
   http_status_t	expect;			/* Expect: header to use */

-
-  DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+  DEBUG_printf(("cupsDoStreamRequest(%p, %p, \'%s\', %p, %p)\n",
                 http, request, resource ? resource : "(null)",
-		filename ? filename : "(null)"));
+		fpread ? fpread : "(null)",
+		arg ? arg : "(null)"));

   if (http == NULL || request == NULL || resource == NULL)
   {
@@ -88,60 +88,6 @@
   }

  /*
-  * See if we have a file to send...
-  */
-
-  if (filename != NULL)
-  {
-    if (stat(filename, &fileinfo))
-    {
-     /*
-      * Can't get file information!
-      */
-
-      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
-                     strerror(errno));
-
-      ippDelete(request);
-
-      return (NULL);
-    }
-
-#ifdef WIN32
-    if (fileinfo.st_mode & _S_IFDIR)
-#else
-    if (S_ISDIR(fileinfo.st_mode))
-#endif /* WIN32 */
-    {
-     /*
-      * Can't send a directory...
-      */
-
-      ippDelete(request);
-
-      _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
-
-      return (NULL);
-    }
-
-    if ((file = fopen(filename, "rb")) == NULL)
-    {
-     /*
-      * Can't open file!
-      */
-
-      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
-                     strerror(errno));
-
-      ippDelete(request);
-
-      return (NULL);
-    }
-  }
-  else
-    file = NULL;
-
- /*
   * Loop until we can send the request without authorization problems.
   */

@@ -151,29 +97,30 @@

   while (response == NULL)
   {
-    DEBUG_puts("cupsDoFileRequest: setup...");
+    DEBUG_puts("cupsDoStreamRequest: setup...");

    /*
     * Setup the HTTP variables needed...
     */

     length = ippLength(request);
-    if (filename)
-      length += fileinfo.st_size;

     httpClearFields(http);
-    httpSetLength(http, length);
+    if (fpread)
+      httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+    else
+      httpSetLength(http, length);
     httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
     httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
     httpSetExpect(http, expect);

-    DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+    DEBUG_printf(("cupsDoStreamRequest: authstring=\"%s\"\n", http->authstring));

    /*
     * Try the request...
     */

-    DEBUG_puts("cupsDoFileRequest: post...");
+    DEBUG_puts("cupsDoStreamRequest: post...");

     if (httpPost(http, resource))
     {
@@ -190,7 +137,7 @@
     * Send the IPP data...
     */

-    DEBUG_puts("cupsDoFileRequest: ipp write...");
+    DEBUG_puts("cupsDoStreamRequest: ipp write...");

     request->state = IPP_IDLE;
     status         = HTTP_CONTINUE;
@@ -219,18 +166,19 @@
     else if (httpCheck(http))
       status = httpUpdate(http);

-    if (status == HTTP_CONTINUE && state == IPP_DATA && filename)
+    DEBUG_printf(("cupsDoStreamRequest: fpread=%p\n", fpread));
+
+    if (status == HTTP_CONTINUE && state == IPP_DATA && fpread)
     {
-      DEBUG_puts("cupsDoFileRequest: file write...");
+      DEBUG_puts("cupsDoStreamRequest: file write...");

      /*
       * Send the file...
       */

-      rewind(file);
-
-      while ((bytes = (int)fread(buffer, 1, sizeof(buffer), file)) > 0)
+      while ((bytes = (int)fpread(buffer, 1, sizeof(buffer), arg)) > 0)
       {
+        DEBUG_printf(("cupsDoStreamRequest: read %d bytes from stream\n", bytes));
 	if (httpCheck(http))
 	{
 	  if ((status = httpUpdate(http)) != HTTP_CONTINUE)
@@ -239,23 +187,28 @@

   	if (httpWrite2(http, buffer, bytes) < bytes)
           break;
+
+        httpFlushWrite(http);
       }
+
+      httpWrite2(http, "", 0);
+      httpFlushWrite(http);
     }

    /*
     * Get the server's return status...
     */

-    DEBUG_puts("cupsDoFileRequest: update...");
+    DEBUG_puts("cupsDoStreamRequest: update...");

     while (status == HTTP_CONTINUE)
       status = httpUpdate(http);

-    DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
+    DEBUG_printf(("cupsDoStreamRequest: status = %d\n", status));

     if (status == HTTP_UNAUTHORIZED)
     {
-      DEBUG_puts("cupsDoFileRequest: unauthorized...");
+      DEBUG_puts("cupsDoStreamRequest: unauthorized...");

      /*
       * Flush any error message...
@@ -280,7 +233,7 @@
     }
     else if (status == HTTP_ERROR)
     {
-      DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
+      DEBUG_printf(("cupsDoStreamRequest: http->error=%d (%s)\n", http->error,
                     strerror(http->error)));

 #ifdef WIN32
@@ -324,7 +277,7 @@
     }
     else if (status != HTTP_OK)
     {
-      DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+      DEBUG_printf(("cupsDoStreamRequest: error %d...\n", status));

      /*
       * Flush any error message...
@@ -339,7 +292,7 @@
       * Read the response...
       */

-      DEBUG_puts("cupsDoFileRequest: response...");
+      DEBUG_puts("cupsDoStreamRequest: response...");

       response = ippNew();

@@ -362,13 +315,6 @@
   }

  /*
-  * Close the file if needed...
-  */
-
-  if (filename != NULL)
-    fclose(file);
-
- /*
   * Flush any remaining data...
   */

@@ -436,6 +382,87 @@


 /*
+ * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary.  The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t *					/* O - Response data */
+cupsDoFileRequest(http_t     *http,	/* I - HTTP connection to server */
+                  ipp_t      *request,	/* I - IPP request */
+                  const char *resource,	/* I - HTTP resource for POST */
+		  const char *filename)	/* I - File to send or NULL for none */
+{
+  FILE		*file;			/* File to send */
+  struct stat	fileinfo;		/* File information */
+  ipp_t		*response;		/* IPP response data */
+
+  DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+                http, request, resource ? resource : "(null)",
+		filename ? filename : "(null)"));
+
+  if (filename != NULL)
+  {
+    if (stat(filename, &fileinfo))
+    {
+     /*
+      * Can't get file information!
+      */
+
+      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+                     strerror(errno));
+
+      ippDelete(request);
+
+      return (NULL);
+    }
+
+#ifdef WIN32
+    if (fileinfo.st_mode & _S_IFDIR)
+#else
+    if (S_ISDIR(fileinfo.st_mode))
+#endif /* WIN32 */
+    {
+     /*
+      * Can't send a directory...
+      */
+
+      ippDelete(request);
+
+      _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
+
+      return (NULL);
+    }
+
+    if ((file = fopen(filename, "rb")) == NULL)
+    {
+     /*
+      * Can't open file!
+      */
+
+      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+                     strerror(errno));
+
+      ippDelete(request);
+
+      return (NULL);
+    }
+  }
+  else
+    file = NULL;
+
+  response = cupsDoStreamRequest(http, request, resource, file ? (cups_stream_cb_t) fread : NULL, file);
+
+  if (file)
+    fclose(file);
+
+  return (response);
+}
+
+
+/*
  * 'cupsDoRequest()' - Do an IPP request.
  *
  * This function sends the IPP request to the specified server, retrying
Index: berkeley/lpr.c
===================================================================
--- berkeley/lpr.c	(revision 6305)
+++ berkeley/lpr.c	(working copy)
@@ -429,70 +429,7 @@
   }
   else
   {
-    num_files = 1;
-
-#ifndef WIN32
-#  if defined(HAVE_SIGSET)
-    sigset(SIGHUP, sighandler);
-    if (sigset(SIGINT, sighandler) == SIG_IGN)
-      sigset(SIGINT, SIG_IGN);
-    sigset(SIGTERM, sighandler);
-#  elif defined(HAVE_SIGACTION)
-    memset(&action, 0, sizeof(action));
-    action.sa_handler = sighandler;
-
-    sigaction(SIGHUP, &action, NULL);
-    sigaction(SIGINT, NULL, &oldaction);
-    if (oldaction.sa_handler != SIG_IGN)
-      sigaction(SIGINT, &action, NULL);
-    sigaction(SIGTERM, &action, NULL);
-#  else
-    signal(SIGHUP, sighandler);
-    if (signal(SIGINT, sighandler) == SIG_IGN)
-      signal(SIGINT, SIG_IGN);
-    signal(SIGTERM, sighandler);
-#  endif
-#endif /* !WIN32 */
-
-    if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
-    {
-      _cupsLangPrintf(stderr,
-                      _("%s: Error - unable to create temporary file "
-		        "\"%s\" - %s\n"),
-        	      argv[0], tempfile, strerror(errno));
-      return (1);
-    }
-
-    while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
-      if (write(temp, buffer, bytes) < 0)
-      {
-	_cupsLangPrintf(stderr,
-	                _("%s: Error - unable to write to temporary file "
-			  "\"%s\" - %s\n"),
-        		argv[0], tempfile, strerror(errno));
-        close(temp);
-        unlink(tempfile);
-	return (1);
-      }
-
-    filesize = lseek(temp, 0, SEEK_CUR);
-    close(temp);
-
-    if (filesize <= 0)
-    {
-      _cupsLangPrintf(stderr,
-                      _("%s: Error - stdin is empty, so no job has been sent.\n"),
-		      argv[0]);
-      unlink(tempfile);
-      return (1);
-    }
-
-    if (title)
-      job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
-    else
-      job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
-
-    unlink(tempfile);
+    job_id = cupsPrintStream(NULL, printer, (cups_stream_cb_t) fread, stdin, title, num_options, options);
   }

   if (job_id < 1)
@@ -504,30 +441,6 @@
   return (0);
 }

-
-#ifndef WIN32
 /*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s)			/* I - Signal number */
-{
- /*
-  * Remove the temporary file we're using to print from stdin...
-  */
-
-  unlink(tempfile);
-
- /*
-  * Exit...
-  */
-
-  exit(s);
-}
-#endif /* !WIN32 */
-
-
-/*
  * End of "$Id$".
  */
Index: cups/cups.h
===================================================================
--- cups/cups.h	(revision 6305)
+++ cups/cups.h	(working copy)
@@ -110,6 +110,8 @@
   CUPS_PRINTER_OPTIONS = 0xe6fffc	/* ~(CLASS | REMOTE | IMPLICIT) */
 };

+typedef size_t (*cups_stream_cb_t)(void *, size_t, size_t, void *);
+               /**** Streaming callback ****/
 typedef const char *(*cups_password_cb_t)(const char *);
 					/**** Password callback ****/

@@ -243,6 +245,15 @@
 			                 cups_option_t **options);
 extern cups_file_t	*cupsTempFile2(char *filename, int len);

+/**** New in CUPS 1.2.? ****/
+extern int		cupsPrintStream(http_t *http, const char *printer,
+			                cups_stream_cb_t fpread, void *arg,
+					const char *title, int num_options,
+					cups_option_t *options);
+extern ipp_t		*cupsDoStreamRequest(http_t *http, ipp_t *request,
+			                     const char *resource,
+					     cups_stream_cb_t fpread,
+					     void *arg);

 #  ifdef __cplusplus
 }
Index: cups/request.c
===================================================================
--- cups/request.c	(revision 6305)
+++ cups/request.c	(working copy)
@@ -36,6 +36,7 @@

 #include "globals.h"
 #include "debug.h"
+#include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -48,34 +49,33 @@


 /*
- * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ * 'cupsDoStreamRequest()' - Do a stream request with a file.
  *
  * This function sends the IPP request to the specified server, retrying
  * and authenticating as necessary.  The request is freed with ippDelete()
  * after receiving a valid IPP response.
  */

-ipp_t *					/* O - Response data */
-cupsDoFileRequest(http_t     *http,	/* I - HTTP connection to server */
-                  ipp_t      *request,	/* I - IPP request */
-                  const char *resource,	/* I - HTTP resource for POST */
-		  const char *filename)	/* I - File to send or NULL for none */
+ipp_t *                                         /* O - Response data */
+cupsDoStreamRequest(http_t           *http,     /* I - HTTP connection to server */
+                    ipp_t            *request,  /* I - IPP request */
+                    const char       *resource, /* I - HTTP resource for POST */
+                    cups_stream_cb_t fpread,    /* I - function pointer for read */
+                    void             *arg)      /* I - arbitrary arg to pass to fp */
 {
   ipp_t		*response;		/* IPP response data */
   size_t	length;			/* Content-Length value */
   http_status_t	status;			/* Status of HTTP request */
   int		got_status;		/* Did we get the status? */
   ipp_state_t	state;			/* State of IPP processing */
-  FILE		*file;			/* File to send */
-  struct stat	fileinfo;		/* File information */
   int		bytes;			/* Number of bytes read/written */
   char		buffer[32768];		/* Output buffer */
   http_status_t	expect;			/* Expect: header to use */

-
-  DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+  DEBUG_printf(("cupsDoStreamRequest(%p, %p, \'%s\', %p, %p)\n",
                 http, request, resource ? resource : "(null)",
-		filename ? filename : "(null)"));
+		fpread ? fpread : "(null)",
+		arg ? arg : "(null)"));

   if (http == NULL || request == NULL || resource == NULL)
   {
@@ -88,60 +88,6 @@
   }

  /*
-  * See if we have a file to send...
-  */
-
-  if (filename != NULL)
-  {
-    if (stat(filename, &fileinfo))
-    {
-     /*
-      * Can't get file information!
-      */
-
-      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
-                     strerror(errno));
-
-      ippDelete(request);
-
-      return (NULL);
-    }
-
-#ifdef WIN32
-    if (fileinfo.st_mode & _S_IFDIR)
-#else
-    if (S_ISDIR(fileinfo.st_mode))
-#endif /* WIN32 */
-    {
-     /*
-      * Can't send a directory...
-      */
-
-      ippDelete(request);
-
-      _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
-
-      return (NULL);
-    }
-
-    if ((file = fopen(filename, "rb")) == NULL)
-    {
-     /*
-      * Can't open file!
-      */
-
-      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
-                     strerror(errno));
-
-      ippDelete(request);
-
-      return (NULL);
-    }
-  }
-  else
-    file = NULL;
-
- /*
   * Loop until we can send the request without authorization problems.
   */

@@ -151,29 +97,30 @@

   while (response == NULL)
   {
-    DEBUG_puts("cupsDoFileRequest: setup...");
+    DEBUG_puts("cupsDoStreamRequest: setup...");

    /*
     * Setup the HTTP variables needed...
     */

     length = ippLength(request);
-    if (filename)
-      length += fileinfo.st_size;

     httpClearFields(http);
-    httpSetLength(http, length);
+    if (fpread)
+      httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+    else
+      httpSetLength(http, length);
     httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
     httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
     httpSetExpect(http, expect);

-    DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+    DEBUG_printf(("cupsDoStreamRequest: authstring=\"%s\"\n", http->authstring));

    /*
     * Try the request...
     */

-    DEBUG_puts("cupsDoFileRequest: post...");
+    DEBUG_puts("cupsDoStreamRequest: post...");

     if (httpPost(http, resource))
     {
@@ -190,7 +137,7 @@
     * Send the IPP data...
     */

-    DEBUG_puts("cupsDoFileRequest: ipp write...");
+    DEBUG_puts("cupsDoStreamRequest: ipp write...");

     request->state = IPP_IDLE;
     status         = HTTP_CONTINUE;
@@ -219,18 +166,19 @@
     else if (httpCheck(http))
       status = httpUpdate(http);

-    if (status == HTTP_CONTINUE && state == IPP_DATA && filename)
+    DEBUG_printf(("cupsDoStreamRequest: fpread=%p\n", fpread));
+
+    if (status == HTTP_CONTINUE && state == IPP_DATA && fpread)
     {
-      DEBUG_puts("cupsDoFileRequest: file write...");
+      DEBUG_puts("cupsDoStreamRequest: file write...");

      /*
       * Send the file...
       */

-      rewind(file);
-
-      while ((bytes = (int)fread(buffer, 1, sizeof(buffer), file)) > 0)
+      while ((bytes = (int)fpread(buffer, 1, sizeof(buffer), arg)) > 0)
       {
+        DEBUG_printf(("cupsDoStreamRequest: read %d bytes from stream\n", bytes));
 	if (httpCheck(http))
 	{
 	  if ((status = httpUpdate(http)) != HTTP_CONTINUE)
@@ -239,23 +187,28 @@

   	if (httpWrite2(http, buffer, bytes) < bytes)
           break;
+
+        httpFlushWrite(http);
       }
+
+      httpWrite2(http, "", 0);
+      httpFlushWrite(http);
     }

    /*
     * Get the server's return status...
     */

-    DEBUG_puts("cupsDoFileRequest: update...");
+    DEBUG_puts("cupsDoStreamRequest: update...");

     while (status == HTTP_CONTINUE)
       status = httpUpdate(http);

-    DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
+    DEBUG_printf(("cupsDoStreamRequest: status = %d\n", status));

     if (status == HTTP_UNAUTHORIZED)
     {
-      DEBUG_puts("cupsDoFileRequest: unauthorized...");
+      DEBUG_puts("cupsDoStreamRequest: unauthorized...");

      /*
       * Flush any error message...
@@ -280,7 +233,7 @@
     }
     else if (status == HTTP_ERROR)
     {
-      DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
+      DEBUG_printf(("cupsDoStreamRequest: http->error=%d (%s)\n", http->error,
                     strerror(http->error)));

 #ifdef WIN32
@@ -324,7 +277,7 @@
     }
     else if (status != HTTP_OK)
     {
-      DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+      DEBUG_printf(("cupsDoStreamRequest: error %d...\n", status));

      /*
       * Flush any error message...
@@ -339,7 +292,7 @@
       * Read the response...
       */

-      DEBUG_puts("cupsDoFileRequest: response...");
+      DEBUG_puts("cupsDoStreamRequest: response...");

       response = ippNew();

@@ -362,13 +315,6 @@
   }

  /*
-  * Close the file if needed...
-  */
-
-  if (filename != NULL)
-    fclose(file);
-
- /*
   * Flush any remaining data...
   */

@@ -436,6 +382,87 @@


 /*
+ * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary.  The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t *					/* O - Response data */
+cupsDoFileRequest(http_t     *http,	/* I - HTTP connection to server */
+                  ipp_t      *request,	/* I - IPP request */
+                  const char *resource,	/* I - HTTP resource for POST */
+		  const char *filename)	/* I - File to send or NULL for none */
+{
+  FILE		*file;			/* File to send */
+  struct stat	fileinfo;		/* File information */
+  ipp_t		*response;		/* IPP response data */
+
+  DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+                http, request, resource ? resource : "(null)",
+		filename ? filename : "(null)"));
+
+  if (filename != NULL)
+  {
+    if (stat(filename, &fileinfo))
+    {
+     /*
+      * Can't get file information!
+      */
+
+      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+                     strerror(errno));
+
+      ippDelete(request);
+
+      return (NULL);
+    }
+
+#ifdef WIN32
+    if (fileinfo.st_mode & _S_IFDIR)
+#else
+    if (S_ISDIR(fileinfo.st_mode))
+#endif /* WIN32 */
+    {
+     /*
+      * Can't send a directory...
+      */
+
+      ippDelete(request);
+
+      _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
+
+      return (NULL);
+    }
+
+    if ((file = fopen(filename, "rb")) == NULL)
+    {
+     /*
+      * Can't open file!
+      */
+
+      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+                     strerror(errno));
+
+      ippDelete(request);
+
+      return (NULL);
+    }
+  }
+  else
+    file = NULL;
+
+  response = cupsDoStreamRequest(http, request, resource, file ? (cups_stream_cb_t) fread : NULL, file);
+
+  if (file)
+    fclose(file);
+
+  return (response);
+}
+
+
+/*
  * 'cupsDoRequest()' - Do an IPP request.
  *
  * This function sends the IPP request to the specified server, retrying
--- snip --- snip --- snip ---




More information about the cups mailing list