+#define WMIN(x, y) ((x) > (y) ? (y) : (x))
+
+/* Send the contents of FILE_NAME to SOCK/SSL. Make sure that exactly
+ PROMISED_SIZE bytes are sent over the wire -- if the file is
+ longer, read only that much; if the file is shorter, pad it with
+ zeros. */
+
+static int
+post_file (int sock, void *ssl, const char *file_name, long promised_size)
+{
+ static char chunk[8192];
+ long written = 0;
+ int write_error;
+ FILE *fp;
+
+ /* Only one of SOCK and SSL may be active at the same time. */
+ assert (sock > -1 || ssl != NULL);
+ assert (sock == -1 || ssl == NULL);
+
+ DEBUGP (("[writing POST file %s ... ", file_name));
+
+ fp = fopen (file_name, "rb");
+ if (!fp)
+ goto pad;
+ while (written < promised_size)
+ {
+ int towrite;
+ int length = fread (chunk, 1, sizeof (chunk), fp);
+ if (length == 0)
+ break;
+ towrite = WMIN (promised_size - written, length);
+#ifdef HAVE_SSL
+ if (ssl)
+ write_error = ssl_iwrite (ssl, chunk, towrite);
+ else
+#endif
+ write_error = iwrite (sock, chunk, towrite);
+ if (write_error < 0)
+ {
+ fclose (fp);
+ return -1;
+ }
+ written += towrite;
+ }
+ fclose (fp);
+
+ pad:
+ if (written < promised_size)
+ {
+ /* This highly unlikely case can happen only if the file has
+ shrunk under us. To uphold the promise that exactly
+ promised_size bytes would be delivered, pad the remaining
+ data with zeros. #### Should we abort instead? */
+ DEBUGP (("padding %ld bytes ... ", promised_size - written));
+ memset (chunk, '\0', sizeof (chunk));
+ while (written < promised_size)
+ {
+ int towrite = WMIN (promised_size - written, sizeof (chunk));
+#ifdef HAVE_SSL
+ if (ssl)
+ write_error = ssl_iwrite (ssl, chunk, towrite);
+ else
+#endif
+ write_error = iwrite (sock, chunk, towrite);
+ if (write_error < 0)
+ return -1;
+ written += towrite;
+ }
+ }
+ assert (written == promised_size);
+ DEBUGP (("done]\n"));
+ return 0;
+}
+\f