Index: src/mapiclient/MapiClient.mx
===================================================================
RCS file: /cvsroot/monetdb/clients/src/mapiclient/MapiClient.mx,v
retrieving revision 1.151.2.1
diff -u -r1.151.2.1 MapiClient.mx
--- src/mapiclient/MapiClient.mx	4 Aug 2009 08:22:44 -0000	1.151.2.1
+++ src/mapiclient/MapiClient.mx	27 Aug 2009 10:36:06 -0000
@@ -1777,6 +1777,76 @@
 	return errseen;
 }
 
+/* note: octalStr must be nul-terminated */
+size_t 
+fetchOctal(char *octalStr) {
+	size_t result = 0;
+	int i = 0;
+	while (octalStr[i] != '\0') {
+		result = (result*8) + ((int)octalStr[i] - '0');
+		i++;
+	}
+	return result;
+}
+
+void
+readTAR(Mapi mid, char *colname, FILE *fp) {
+	size_t length, result;
+	char buf[BUFSIZ];
+	MapiMsg rc;
+
+	/* see http://en.wikipedia.org/wiki/Tar_(file_format) */
+	char *fileNameStr = buf + 0; 
+	char *fileSizeStr = buf + 124; 
+	char *docName;
+	int fileType = 156;
+
+	/* repeat */
+	while (1) {
+		/* - read 512-byte header */
+		result = fread(buf, 1, 512, fp);
+
+		/* - if EOF break */
+		if (result == 0)
+			break;
+		if (result != 512) {
+			fprintf(stderr, "TAR file format exception: unexpected EOF, expected 512-byte blocks\n");
+			exit(1);
+		}
+
+		if (buf[fileType] != '0')
+			continue;
+
+		/* - fetch name from header */
+		docName = fileNameStr;
+		buf[99] = '\0'; /* make sure the filename is nul-terminated */
+		
+		/* - fetch size from header */
+		fileSizeStr[11] = '\0'; /* make sure the size-string is nul-terminated */
+		length = fetchOctal(fileSizeStr);
+		fprintf(stderr, "Name: %s Length: %d\n", docName, (int)length);
+		
+		/* FIXME: if empty file, or no .xml, skip */
+		/* FIXME: construct docName */
+
+		/* - read document */
+                rc = mapi_stream_into(mid, docName, colname, stdin, length);
+                if (rc != MOK) {
+                        mapi_explain(mid, stderr);
+                        exit(1);
+                }
+		
+		/* - align on 512-byte boundary */
+		length = 512 - (length % 512);
+		result = fread(buf, 1, length, fp);
+		if (result != length) {
+			fprintf(stderr, "TAR file format exception: unexpected EOF, expected 512-byte blocks\n");
+                        exit(1);
+		}
+	}
+}
+
+
 static void
 usage(const char *prog)
 {
@@ -2118,11 +2188,18 @@
 	if (formatter == NOformatter)
 		formatter = interactive && interactive_stdin && mode != XQUERY && mode != MAL ? TABLEformatter : RAWformatter;
 
+	if (colname != NULL && input == NULL && mode == XQUERY) {
+		/* try to read a tar file from stdin... */
+		fprintf(stderr, "Copying TAR file into collection: '%s'\n", colname);
+		readTAR(mid, colname, stdin);
+		interactive = 0;
+	}
+
 	if (input != NULL && mode == XQUERY) {
 		/* stream xml document into the server */
 		MapiMsg rc;
 
-		rc = mapi_stream_into(mid, input, colname, stdin);
+		rc = mapi_stream_into(mid, input, colname, stdin, SSIZE_MAX);
 		if (rc != MOK) {
 			mapi_explain(mid, stderr);
 			exit(1);
Index: src/mapilib/Mapi.mx
===================================================================
RCS file: /cvsroot/monetdb/clients/src/mapilib/Mapi.mx,v
retrieving revision 1.79.2.2
diff -u -r1.79.2.2 Mapi.mx
--- src/mapilib/Mapi.mx	6 Aug 2009 07:03:15 -0000	1.79.2.2
+++ src/mapilib/Mapi.mx	27 Aug 2009 10:36:10 -0000
@@ -739,7 +739,7 @@
 
 Set the output format for results send by the server.
 
-@item MapiMsg  mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp)
+@item MapiMsg  mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp, size_t size)
 
 Stream a document into the server.  The name of the document is
 specified in docname, the collection is optionally specified in
@@ -1184,7 +1184,7 @@
 mapi_export MapiMsg mapi_explain_query(MapiHdl hdl, FILE *fd);
 mapi_export MapiMsg mapi_explain_result(MapiHdl hdl, FILE *fd);
 mapi_export MapiMsg mapi_output(Mapi mid, char *output);
-mapi_export MapiMsg mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp);
+mapi_export MapiMsg mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp, size_t size);
 mapi_export MapiMsg mapi_profile(Mapi mid, int flag);
 mapi_export MapiMsg mapi_trace(Mapi mid, int flag);
 mapi_export int mapi_get_trace(Mapi mid);
@@ -3345,8 +3345,13 @@
 	return MOK;
 }
 
+/*
+ * Size must be the size of the file to read from the stream
+ * or SSIZE_MAX if unknown. In case of SSIZE_MAX, the stream will be read until
+ * EOF.
+ */
 MapiMsg
-mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp)
+mapi_stream_into(Mapi mid, char *docname, char *colname, FILE *fp, size_t size)
 {
 	char buf[BUFSIZ];
 	int i;
@@ -3355,6 +3360,7 @@
 	MapiHdl hdl;
 	char *err;
 
+
 	mapi_clrError(mid);
 	if (mid->languageId != LANG_XQUERY)
 		mapi_setError(mid, "only allowed in XQuery mode", "mapi_stream_into", MERROR);
@@ -3365,9 +3371,10 @@
 	rc = mapi_Xcommand(mid, "copy", buf);
 	if (rc != MOK)
 		return rc;
-	while ((length = fread(buf, 1, sizeof(buf), fp)) > 0) {
+	while ((length = fread(buf, 1, (sizeof(buf) < size) ? sizeof(buf) : size, fp)) > 0) {
 		stream_write(mid->to, buf, 1, length);
 		check_stream(mid, mid->to, "write error on stream", "mapi_stream_into", mid->error);
+		size -= length;
 	}
 	stream_flush(mid->to);
 	check_stream(mid, mid->to, "write error on stream", "mapi_stream_into", mid->error);
