Getting files immediately to file descriptor.
diff --git a/ChangeLog b/ChangeLog
index fb4679a..c6c5325 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,11 @@
 2006-08-21  Linus Walleij <[email protected]>
 
 	* src/libmtp.c: fixup mmap() usage and add madvise() 
-	  as result of experiments by Gavin McCullagh.
+	  as result of experiments by Gavin McCullagh. Upstream
+	  accept patch to get files directly to file descriptor.
+	* src/ptp.c: sync to upstream which merges patch to get
+	  file directly to file descriptor.
+	* src/ptp.h: dito.
 
 2006-08-20  Linus Walleij <[email protected]>
 
diff --git a/src/libmtp.c b/src/libmtp.c
index 714fd54..56dd79f 100644
--- a/src/libmtp.c
+++ b/src/libmtp.c
@@ -1999,10 +1999,8 @@
 					void const * const data)
 {
   PTPObjectInfo oi;
-  unsigned char *image = NULL;
   uint16_t ret;
   PTPParams *params = (PTPParams *) device->params;
-  ssize_t written;
 
   if (ptp_getobjectinfo(params, id, &oi) != PTP_RC_OK) {
     printf("LIBMTP_Get_File_To_File_Descriptor(): Could not get object info\n");
@@ -2013,23 +2011,14 @@
     return -1;
   }
 
-  // Copy object to memory
-  // We could use ptp_getpartialobject to make for progress bars etc.
-  ret = ptp_getobject(params, id, &image);
-
-  // If we get this into upstream, use this.
-  // ret = ptp_getobject_tofd(params, id, fd);
+  // This now exist in upstream
+  ret = ptp_getobject_tofd(params, id, fd);
   
   if (ret != PTP_RC_OK) {
     printf("LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device (%d)\n", ret);
     return -1;
   }
   
-  written = write(fd, image, oi.ObjectCompressedSize);
-  if (written != oi.ObjectCompressedSize) {
-    printf("LIBMTP_Get_File_To_File_Descriptor(): Could not write object properly\n");
-  }
-
   return 0;
 }
 
diff --git a/src/ptp.c b/src/ptp.c
index 61b4f8b..b663ffd 100644
--- a/src/ptp.c
+++ b/src/ptp.c
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #ifdef ENABLE_NLS
 #  include <libintl.h>
@@ -167,13 +168,17 @@
 
 uint16_t
 ptp_usb_getdata (PTPParams* params, PTPContainer* ptp,
-		unsigned char **data, unsigned int *readlen)
+                 unsigned char **data, unsigned int *readlen,
+                 int to_fd)
 {
 	uint16_t ret;
 	PTPUSBBulkContainer usbdata;
 
 	PTP_CNT_INIT(usbdata);
-	if (*data!=NULL) return PTP_ERROR_BADPARAM;
+
+	if (to_fd == -1 &&  *data != NULL)
+		return PTP_ERROR_BADPARAM;
+
 	do {
 		unsigned int len, rlen;
 		/* read the header and potentially the first data */
@@ -209,25 +214,85 @@
 		if (dtoh32(usbdata.length) > 12 && (rlen==12))
 			params->split_header_data = 1;
 
-		/* Allocate memory for data. */
-		*data=calloc(len,1);
-		if (readlen)
-			*readlen = len;
+		if (to_fd == -1) {
+			/* Allocate memory for data. */
+			*data=calloc(len,1);
+			if (readlen)
+				*readlen = len;
 
-		/* Copy first part of data to 'data' */
-		memcpy(*data,usbdata.payload.data,rlen - PTP_USB_BULK_HDR_LEN);
+			/* Copy first part of data to 'data' */
+			memcpy(*data,usbdata.payload.data,rlen - PTP_USB_BULK_HDR_LEN);
 
-		/* Is that all of data? */
-		if (len+PTP_USB_BULK_HDR_LEN<=rlen) break;
+			/* Is that all of data? */
+			if (len+PTP_USB_BULK_HDR_LEN<=rlen) break;
 
-		/* If not read the rest of it. */
-		ret=params->read_func(((unsigned char *)(*data))+
-					rlen - PTP_USB_BULK_HDR_LEN,
-					len-(rlen - PTP_USB_BULK_HDR_LEN),
-					params->data, &rlen);
-		if (ret!=PTP_RC_OK) {
-			ret = PTP_ERROR_IO;
-			break;
+			/* If not read the rest of it. */
+			ret=params->read_func(((unsigned char *)(*data))+
+					      rlen - PTP_USB_BULK_HDR_LEN,
+					      len-(rlen - PTP_USB_BULK_HDR_LEN),
+					      params->data, &rlen);
+			if (ret!=PTP_RC_OK) {
+				ret = PTP_ERROR_IO;
+				break;
+			}
+		} else {
+			uint32_t bytes_to_write, written;
+			uint32_t bytes_left_to_transfer;
+			uint32_t temp_buf_size = 0x100000;
+			void *temp_buf;
+						
+			if (readlen)
+				*readlen = len;
+
+			bytes_to_write = rlen - PTP_USB_BULK_HDR_LEN;
+
+			ret = write(to_fd, usbdata.payload.data, bytes_to_write);
+			if (ret != bytes_to_write) {
+				ret = PTP_ERROR_IO;
+				break;
+			}
+
+			if (len + PTP_USB_BULK_HDR_LEN <= rlen)
+				break;
+			
+			temp_buf = malloc(temp_buf_size);
+			if (temp_buf == NULL) {
+				ret = PTP_ERROR_IO;
+				break;
+			}
+
+			ret = PTP_RC_OK;				
+			bytes_left_to_transfer = len - (rlen - PTP_USB_BULK_HDR_LEN);
+
+			while (bytes_left_to_transfer > 0) {
+				bytes_to_write = ((bytes_left_to_transfer > temp_buf_size) ?
+						  temp_buf_size : bytes_left_to_transfer);
+				
+				ret = params->read_func(temp_buf,
+							bytes_to_write,
+							params->data, &rlen);
+
+				if (ret != PTP_RC_OK) {
+					ret = PTP_ERROR_IO;
+					break;
+				}
+
+				written = write(to_fd, temp_buf, bytes_to_write);
+				if (written != bytes_to_write) {
+					ret = PTP_ERROR_IO;
+					break;
+				} else {
+					ret = PTP_RC_OK;
+				}
+
+				bytes_left_to_transfer -= bytes_to_write;
+			}
+
+			free(temp_buf);
+
+			if (ret != PTP_RC_OK)
+				break;
+
 		}
 	} while (0);
 /*
@@ -315,9 +380,9 @@
  * all fields filled in.
  **/
 static uint16_t
-ptp_transaction (PTPParams* params, PTPContainer* ptp, 
-		uint16_t flags, unsigned int sendlen, unsigned char** data,
-		unsigned int *recvlen)
+_ptp_transaction (PTPParams* params, PTPContainer* ptp, 
+		  uint16_t flags, unsigned int sendlen, unsigned char** data,
+		  int to_fd, unsigned int *recvlen)
 {
 	if ((params==NULL) || (ptp==NULL)) 
 		return PTP_ERROR_BADPARAM;
@@ -334,7 +399,7 @@
 		break;
 	case PTP_DP_GETDATA:
 		CHECK_PTP_RC(params->getdata_func(params, ptp,
-			(unsigned char**)data, recvlen));
+			(unsigned char**)data, recvlen, to_fd));
 		break;
 	case PTP_DP_NODATA:
 		break;
@@ -347,6 +412,22 @@
 	return ptp->Code;
 }
 
+static uint16_t
+ptp_transaction (PTPParams* params, PTPContainer* ptp, 
+		 uint16_t flags, unsigned int sendlen, unsigned char** data,
+		 unsigned int *recvlen)
+{
+	return _ptp_transaction(params, ptp, flags, sendlen, data, -1, recvlen);
+}
+
+static uint16_t
+ptp_transaction_tofd (PTPParams* params, PTPContainer* ptp, 
+		      uint16_t flags, unsigned int sendlen, 
+		      int to_fd, unsigned int *recvlen)
+{
+	return _ptp_transaction(params, ptp, flags, sendlen, NULL, to_fd, recvlen);
+}
+
 /* Enets handling functions */
 
 /* PTP Events wait for or check mode */
@@ -684,6 +765,31 @@
 }
 
 /**
+ * ptp_getobject_tofd:
+ * params:	PTPParams*
+ *		handle			- Object handle
+ *		fd                      - File descriptor to write() to
+ *
+ * Get object 'handle' from device and write the data to the 
+ * given file descriptor.
+ *
+ * Return values: Some PTP_RC_* code.
+ **/
+uint16_t
+ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd)
+{
+	PTPContainer ptp;
+	unsigned int len;
+
+	PTP_CNT_INIT(ptp);
+	ptp.Code=PTP_OC_GetObject;
+	ptp.Param1=handle;
+	ptp.Nparam=1;
+	len=0;
+	return ptp_transaction_tofd(params, &ptp, PTP_DP_GETDATA, 0, fd, &len);
+}
+
+/**
  * ptp_getpartialobject:
  * params:	PTPParams*
  *		handle			- Object handle
diff --git a/src/ptp.h b/src/ptp.h
index 5031a85..002ec2b 100644
--- a/src/ptp.h
+++ b/src/ptp.h
@@ -1045,7 +1045,8 @@
 					unsigned char *data, unsigned int size);
 typedef uint16_t (* PTPIOGetResp)	(PTPParams* params, PTPContainer* resp);
 typedef uint16_t (* PTPIOGetData)	(PTPParams* params, PTPContainer* ptp,
-					unsigned char **data, unsigned int *recvlen);
+	                                unsigned char **data, unsigned int *recvlen,
+	                                int to_fd);
 /* debug functions */
 typedef void (* PTPErrorFunc) (void *data, const char *format, va_list args)
 #if (__GNUC__ >= 3)
@@ -1114,7 +1115,8 @@
 				unsigned char *data, unsigned int size);
 uint16_t ptp_usb_getresp	(PTPParams* params, PTPContainer* resp);
 uint16_t ptp_usb_getdata	(PTPParams* params, PTPContainer* ptp, 
-				unsigned char **data, unsigned int *readlen);
+				 unsigned char **data, unsigned int *readlen,
+	                         int to_fd);
 uint16_t ptp_usb_event_check	(PTPParams* params, PTPContainer* event);
 uint16_t ptp_usb_event_wait	(PTPParams* params, PTPContainer* event);
 
@@ -1124,7 +1126,8 @@
 				unsigned char *data, unsigned int size);
 uint16_t ptp_ptpip_getresp	(PTPParams* params, PTPContainer* resp);
 uint16_t ptp_ptpip_getdata	(PTPParams* params, PTPContainer* ptp, 
-				unsigned char **data, unsigned int *readlen);
+				 unsigned char **data, unsigned int *readlen,
+	                         int to_fd);
 uint16_t ptp_ptpip_event_wait	(PTPParams* params, PTPContainer* event);
 uint16_t ptp_ptpip_event_check	(PTPParams* params, PTPContainer* event);
 
@@ -1152,6 +1155,7 @@
 
 uint16_t ptp_getobject		(PTPParams *params, uint32_t handle,
 				unsigned char** object);
+uint16_t ptp_getobject_tofd     (PTPParams* params, uint32_t handle, int fd);
 uint16_t ptp_getpartialobject	(PTPParams* params, uint32_t handle, uint32_t offset,
 				uint32_t maxbytes, unsigned char** object);
 uint16_t ptp_getthumb		(PTPParams *params, uint32_t handle,