/*
 * Copyright (C) 2017 TeamWin
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include "../twcommon.h"
#include "../set_metadata.h"
#include <cutils/properties.h>

#include "MtpTypes.h"
#include "MtpDebug.h"
#include "MtpDatabase.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpServer.h"
#include "MtpStorage.h"
#include "MtpStringBuffer.h"

#include <linux/usb/f_mtp.h>

static const MtpOperationCode kSupportedOperationCodes[] = {
	MTP_OPERATION_GET_DEVICE_INFO,
	MTP_OPERATION_OPEN_SESSION,
	MTP_OPERATION_CLOSE_SESSION,
	MTP_OPERATION_GET_STORAGE_IDS,
	MTP_OPERATION_GET_STORAGE_INFO,
	MTP_OPERATION_GET_NUM_OBJECTS,
	MTP_OPERATION_GET_OBJECT_HANDLES,
	MTP_OPERATION_GET_OBJECT_INFO,
	MTP_OPERATION_GET_OBJECT,
	MTP_OPERATION_GET_THUMB,
	MTP_OPERATION_DELETE_OBJECT,
	MTP_OPERATION_SEND_OBJECT_INFO,
	MTP_OPERATION_SEND_OBJECT,
//	MTP_OPERATION_INITIATE_CAPTURE,
//	MTP_OPERATION_FORMAT_STORE,
//	MTP_OPERATION_RESET_DEVICE,
//	MTP_OPERATION_SELF_TEST,
//	MTP_OPERATION_SET_OBJECT_PROTECTION,
//	MTP_OPERATION_POWER_DOWN,
	MTP_OPERATION_GET_DEVICE_PROP_DESC,
	MTP_OPERATION_GET_DEVICE_PROP_VALUE,
	MTP_OPERATION_SET_DEVICE_PROP_VALUE,
	MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
//	MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
//	MTP_OPERATION_MOVE_OBJECT,
//	MTP_OPERATION_COPY_OBJECT,
	MTP_OPERATION_GET_PARTIAL_OBJECT,
//	MTP_OPERATION_INITIATE_OPEN_CAPTURE,
	MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
	MTP_OPERATION_GET_OBJECT_PROP_DESC,
	MTP_OPERATION_GET_OBJECT_PROP_VALUE,
	MTP_OPERATION_SET_OBJECT_PROP_VALUE,
	MTP_OPERATION_GET_OBJECT_PROP_LIST,
//	MTP_OPERATION_SET_OBJECT_PROP_LIST,
//	MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
//	MTP_OPERATION_SEND_OBJECT_PROP_LIST,
	MTP_OPERATION_GET_OBJECT_REFERENCES,
	MTP_OPERATION_SET_OBJECT_REFERENCES,
//	MTP_OPERATION_SKIP,
	// Android extension for direct file IO
	MTP_OPERATION_GET_PARTIAL_OBJECT_64,
	MTP_OPERATION_SEND_PARTIAL_OBJECT,
	MTP_OPERATION_TRUNCATE_OBJECT,
	MTP_OPERATION_BEGIN_EDIT_OBJECT,
	MTP_OPERATION_END_EDIT_OBJECT,
};

static const MtpEventCode kSupportedEventCodes[] = {
	MTP_EVENT_OBJECT_ADDED,
	MTP_EVENT_OBJECT_REMOVED,
	MTP_EVENT_STORE_ADDED,
	MTP_EVENT_STORE_REMOVED,
	MTP_EVENT_OBJECT_PROP_CHANGED,
};

MtpServer::MtpServer(MtpDatabase* database, bool ptp,
					int fileGroup, int filePerm, int directoryPerm)
	:	mDatabase(database),
		mPtp(ptp),
		mFileGroup(fileGroup),
		mFilePermission(filePerm),
		mDirectoryPermission(directoryPerm),
		mSessionID(0),
		mSessionOpen(false),
		mSendObjectHandle(kInvalidObjectHandle),
		mSendObjectFormat(0),
		mSendObjectFileSize(0)
{
	mFD = -1;
}

MtpServer::~MtpServer() {
}

void MtpServer::addStorage(MtpStorage* storage) {
	android::Mutex::Autolock autoLock(mMutex);
	MTPD("addStorage(): storage: %x\n", storage);
	if (getStorage(storage->getStorageID()) != NULL) {
		MTPE("MtpServer::addStorage Storage for storage ID %i already exists.\n", storage->getStorageID());
		return;
	}
	mDatabase->createDB(storage, storage->getStorageID());
	mStorages.push(storage);
	sendStoreAdded(storage->getStorageID());
}

void MtpServer::removeStorage(MtpStorage* storage) {
	android::Mutex::Autolock autoLock(mMutex);

	for (size_t i = 0; i < mStorages.size(); i++) {
		if (mStorages[i] == storage) {
			MTPD("MtpServer::removeStorage calling sendStoreRemoved\n");
			// First lock the mutex so that the inotify thread and main
			// thread do not do anything while we remove the storage
			// item, and to make sure we don't remove the item while an
			// operation is in progress
			mDatabase->lockMutex();
			// Grab the storage ID before we delete the item from the
			// database
			MtpStorageID storageID = storage->getStorageID();
			// Remove the item from the mStorages from the vector. At
			// this point the main thread will no longer be able to find
			// this storage item anymore.
			mStorages.removeAt(i);
			// Destroy the storage item, free up all the memory, kill
			// the inotify thread.
			mDatabase->destroyDB(storageID);
			// Tell the host OS that the storage item is gone.
			sendStoreRemoved(storageID);
			// Unlock any remaining mutexes on other storage devices.
			// If no storage devices exist anymore this will do nothing.
			mDatabase->unlockMutex();
			break;
		}
	}
	MTPD("MtpServer::removeStorage DONE\n");
}

MtpStorage* MtpServer::getStorage(MtpStorageID id) {
	MTPD("getStorage\n");
	if (id == 0) {
		MTPD("mStorages\n");
		return mStorages[0];
	}
	for (size_t i = 0; i < mStorages.size(); i++) {
		MtpStorage* storage = mStorages[i];
		MTPD("id: %d\n", id);
		MTPD("storage: %d\n", storage->getStorageID());
		if (storage->getStorageID() == id) {
			return storage;
		}
	}
	return NULL;
}

bool MtpServer::hasStorage(MtpStorageID id) {
	MTPD("in hasStorage\n");
	if (id == 0 || id == 0xFFFFFFFF)
		return mStorages.size() > 0;
	return (getStorage(id) != NULL);
}

void MtpServer::run(int fd) {
	if (fd < 0)
		return;

	mFD = fd;
	MTPI("MtpServer::run fd: %d\n", fd);

	while (1) {
		MTPD("About to read device...\n");
		int ret = mRequest.read(fd);
		if (ret < 0) {
			if (errno == ECANCELED) {
				// return to top of loop and wait for next command
				MTPD("request read returned %d ECANCELED, starting over\n", ret);
				continue;
			}
			MTPE("request read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
			break;
		}
		MtpOperationCode operation = mRequest.getOperationCode();
		MtpTransactionID transaction = mRequest.getTransactionID();

		MTPD("operation: %s", MtpDebug::getOperationCodeName(operation));
		mRequest.dump();

		// FIXME need to generalize this
		bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
					|| operation == MTP_OPERATION_SET_OBJECT_REFERENCES
					|| operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
					|| operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
		if (dataIn) {
			int ret = mData.read(fd);
			if (ret < 0) {
				if (errno == ECANCELED) {
					// return to top of loop and wait for next command
					MTPD("data read returned %d ECANCELED, starting over\n", ret);
					continue;
				}
				MTPD("data read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
				break;
			}
			MTPD("received data:");
			mData.dump();
		} else {
			mData.reset();
		}

		if (handleRequest()) {
			if (!dataIn && mData.hasData()) {
				mData.setOperationCode(operation);
				mData.setTransactionID(transaction);
				MTPD("sending data:");
				mData.dump();
				ret = mData.write(fd);
				if (ret < 0) {
					if (errno == ECANCELED) {
						// return to top of loop and wait for next command
						MTPD("data write returned %d ECANCELED, starting over\n", ret);
						continue;
					}
					MTPE("data write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
					break;
				}
			}

			mResponse.setTransactionID(transaction);
			MTPD("sending response %04X\n", mResponse.getResponseCode());
			ret = mResponse.write(fd);
			MTPD("ret: %d\n", ret);
			mResponse.dump();
			if (ret < 0) {
				if (errno == ECANCELED) {
					// return to top of loop and wait for next command
					MTPD("response write returned %d ECANCELED, starting over\n", ret);
					continue;
				}
				MTPE("response write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
				break;
			}
		} else {
			MTPD("skipping response\n");
		}
	}

	// commit any open edits
	int count = mObjectEditList.size();
	for (int i = 0; i < count; i++) {
		ObjectEdit* edit = mObjectEditList[i];
		commitEdit(edit);
		delete edit;
	}
	mObjectEditList.clear();

	if (mSessionOpen)
		mDatabase->sessionEnded(); // This doesn't actually do anything but was carry over from AOSP
	close(fd);
	mFD = -1;
}

void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
	MTPD("sendObjectAdded %d\n", handle);
	sendEvent(MTP_EVENT_OBJECT_ADDED, handle);
}

void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
	MTPD("sendObjectRemoved %d\n", handle);
	sendEvent(MTP_EVENT_OBJECT_REMOVED, handle);
}

void MtpServer::sendObjectUpdated(MtpObjectHandle handle) {
	MTPD("sendObjectUpdated %d\n", handle);
	sendEvent(MTP_EVENT_OBJECT_PROP_CHANGED, handle);
}

void MtpServer::sendStoreAdded(MtpStorageID id) {
	MTPD("sendStoreAdded %08X\n", id);
	sendEvent(MTP_EVENT_STORE_ADDED, id);
}

void MtpServer::sendStoreRemoved(MtpStorageID id) {
	MTPD("sendStoreRemoved %08X\n", id);
	sendEvent(MTP_EVENT_STORE_REMOVED, id);
	MTPD("MtpServer::sendStoreRemoved done\n");
}

void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
	MTPD("MtpServer::sendEvent sending event code: %x\n", code);
	if (mSessionOpen) {
		mEvent.setEventCode(code);
		mEvent.setTransactionID(mRequest.getTransactionID());
		mEvent.setParameter(1, param1);
		int ret = mEvent.write(mFD);
		MTPD("mEvent.write returned %d\n", ret);
	}
}

void MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path,
		uint64_t size, MtpObjectFormat format, int fd) {
	ObjectEdit*  edit = new ObjectEdit(handle, path, size, format, fd);
	mObjectEditList.add(edit);
}

MtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) {
	int count = mObjectEditList.size();
	for (int i = 0; i < count; i++) {
		ObjectEdit* edit = mObjectEditList[i];
		if (edit->mHandle == handle) return edit;
	}
	return NULL;
}

void MtpServer::removeEditObject(MtpObjectHandle handle) {
	int count = mObjectEditList.size();
	for (int i = 0; i < count; i++) {
		ObjectEdit* edit = mObjectEditList[i];
		if (edit->mHandle == handle) {
			delete edit;
			mObjectEditList.removeAt(i);
			return;
		}
	}
	MTPE("ObjectEdit not found in removeEditObject");
}

void MtpServer::commitEdit(ObjectEdit* edit) {
	mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true);
}


bool MtpServer::handleRequest() {
	android::Mutex::Autolock autoLock(mMutex);

	MtpOperationCode operation = mRequest.getOperationCode();
	MtpResponseCode response;

	mResponse.reset();

	if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) {
		// FIXME - need to delete mSendObjectHandle from the database
		MTPE("expected SendObject after SendObjectInfo");
		mSendObjectHandle = kInvalidObjectHandle;
	}

	switch (operation) {
		case MTP_OPERATION_GET_DEVICE_INFO:
				MTPD("doGetDeviceInfo()\n");
				response = doGetDeviceInfo();
				break;
			case MTP_OPERATION_OPEN_SESSION:
				MTPD("doOpenSesion()\n");
				response = doOpenSession();
				break;
			case MTP_OPERATION_CLOSE_SESSION:
				MTPD("doCloseSession()\n");
				response = doCloseSession();
				break;
			case MTP_OPERATION_GET_STORAGE_IDS:
				MTPD("doGetStorageIDs()\n");
				response = doGetStorageIDs();
				break;
		 	 case MTP_OPERATION_GET_STORAGE_INFO:
				MTPD("about to call doGetStorageInfo()\n");
				response = doGetStorageInfo();
				break;
			case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED:
				MTPD("about to call doGetObjectPropsSupported()\n");
				response = doGetObjectPropsSupported();
				break;
			case MTP_OPERATION_GET_OBJECT_HANDLES:
				MTPD("about to call doGetObjectHandles()\n");
				response = doGetObjectHandles();
				break;
			case MTP_OPERATION_GET_NUM_OBJECTS:
				MTPD("about to call doGetNumbObjects()\n");
				response = doGetNumObjects();
				break;
			case MTP_OPERATION_GET_OBJECT_REFERENCES:
				MTPD("about to call doGetObjectReferences()\n");
				response = doGetObjectReferences();
				break;
			case MTP_OPERATION_SET_OBJECT_REFERENCES:
				MTPD("about to call doSetObjectReferences()\n");
				response = doSetObjectReferences();
				break;
			case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
				MTPD("about to call doGetObjectPropValue()\n");
				response = doGetObjectPropValue();
				break;
			case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
				MTPD("about to call doSetObjectPropValue()\n");
				response = doSetObjectPropValue();
				break;
			case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
				MTPD("about to call doGetDevicPropValue()\n");
				response = doGetDevicePropValue();
				break;
			case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
				MTPD("about to call doSetDevicePropVaue()\n");
				response = doSetDevicePropValue();
				break;
			case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
				MTPD("about to call doResetDevicePropValue()\n");
				response = doResetDevicePropValue();
				break;
			case MTP_OPERATION_GET_OBJECT_PROP_LIST:
				MTPD("calling doGetObjectPropList()\n");
				response = doGetObjectPropList();
				break;
			case MTP_OPERATION_GET_OBJECT_INFO:
				MTPD("calling doGetObjectInfo()\n");
				response = doGetObjectInfo();
				break;
			case MTP_OPERATION_GET_OBJECT:
				MTPD("about to call doGetObject()\n");
				response = doGetObject();
				break;
			case MTP_OPERATION_GET_THUMB:
				response = doGetThumb();
				break;
			case MTP_OPERATION_GET_PARTIAL_OBJECT:
			case MTP_OPERATION_GET_PARTIAL_OBJECT_64:
				response = doGetPartialObject(operation);
				break;
			case MTP_OPERATION_SEND_OBJECT_INFO:
				MTPD("about to call doSendObjectInfo()\n");
				response = doSendObjectInfo();
				break;
			case MTP_OPERATION_SEND_OBJECT:
				MTPD("about to call doSendObject()\n");
				response = doSendObject();
				break;
			case MTP_OPERATION_DELETE_OBJECT:
				response = doDeleteObject();
				break;
			case MTP_OPERATION_GET_OBJECT_PROP_DESC:
				MTPD("about to call doGetObjectPropDesc()\n");
				response = doGetObjectPropDesc();
				break;
			case MTP_OPERATION_GET_DEVICE_PROP_DESC:
				MTPD("about to call doGetDevicePropDesc()\n");
				response = doGetDevicePropDesc();
				break;
			case MTP_OPERATION_SEND_PARTIAL_OBJECT:
				response = doSendPartialObject();
				break;
			case MTP_OPERATION_TRUNCATE_OBJECT:
				response = doTruncateObject();
				break;
			case MTP_OPERATION_BEGIN_EDIT_OBJECT:
				response = doBeginEditObject();
				break;
			case MTP_OPERATION_END_EDIT_OBJECT:
				response = doEndEditObject();
				break;
			default:
				MTPE("got unsupported command %s", MtpDebug::getOperationCodeName(operation));
				response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
				break;
		}

		if (response == MTP_RESPONSE_TRANSACTION_CANCELLED)
			return false;
		mResponse.setResponseCode(response);
		return true;
}

MtpResponseCode MtpServer::doGetDeviceInfo() {
	MtpStringBuffer   string;
	char prop_value[PROPERTY_VALUE_MAX];

	MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
	MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
	MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();

	// fill in device info
	mData.putUInt16(MTP_STANDARD_VERSION);
	if (mPtp) {
		MTPD("doGetDeviceInfo putting 0\n");
		mData.putUInt32(0);
	} else {
		// MTP Vendor Extension ID
		MTPD("doGetDeviceInfo putting 6\n");
		mData.putUInt32(6);
	}
	mData.putUInt16(MTP_STANDARD_VERSION);
	if (mPtp) {
		// no extensions
		MTPD("doGetDeviceInfo no extensions\n");
		string.set("");
	} else {
		// MTP extensions
		MTPD("doGetDeviceInfo microsoft.com: 1.0; android.com: 1.0;\n");
		string.set("microsoft.com: 1.0; android.com: 1.0;");
	}
	mData.putString(string); // MTP Extensions
	mData.putUInt16(0); //Functional Mode
	MTPD("doGetDeviceInfo opcodes, %i\n", sizeof(kSupportedOperationCodes) / sizeof(uint16_t));
	MTPD("doGetDeviceInfo eventcodes, %i\n", sizeof(kSupportedEventCodes) / sizeof(uint16_t));
	mData.putAUInt16(kSupportedOperationCodes,
			sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
	mData.putAUInt16(kSupportedEventCodes,
			sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
	mData.putAUInt16(deviceProperties); // Device Properties Supported
	mData.putAUInt16(captureFormats); // Capture Formats
	mData.putAUInt16(playbackFormats);  // Playback Formats

	property_get("ro.product.manufacturer", prop_value, "unknown manufacturer");
	MTPD("prop: %s\n", prop_value);
	string.set(prop_value);
	mData.putString(string);   // Manufacturer

	property_get("ro.product.model", prop_value, "MTP Device");
	string.set(prop_value);
	mData.putString(string);   // Model
	string.set("1.0");
	mData.putString(string);   // Device Version

	property_get("ro.serialno", prop_value, "????????");
	MTPD("sn: %s\n", prop_value);
	string.set(prop_value);
	mData.putString(string);   // Serial Number

	delete playbackFormats;
	delete captureFormats;
	delete deviceProperties;

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doOpenSession() {
	if (mSessionOpen) {
		mResponse.setParameter(1, mSessionID);
		return MTP_RESPONSE_SESSION_ALREADY_OPEN;
	}
	mSessionID = mRequest.getParameter(1);
	mSessionOpen = true;

	mDatabase->sessionStarted();

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doCloseSession() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	mSessionID = 0;
	mSessionOpen = false;
	mDatabase->sessionEnded();
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetStorageIDs() {
	MTPD("doGetStorageIDs()\n");
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	int count = mStorages.size();
	mData.putUInt32(count);
	for (int i = 0; i < count; i++) {
		MTPD("getting storageid %d\n", mStorages[i]->getStorageID());
		mData.putUInt32(mStorages[i]->getStorageID());
	}

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetStorageInfo() {
	MtpStringBuffer   string;
	MTPD("doGetStorageInfo()\n");
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	MtpStorageID id = mRequest.getParameter(1);
	MtpStorage* storage = getStorage(id);
	if (!storage) {
		MTPE("invalid storage id\n");
		return MTP_RESPONSE_INVALID_STORAGE_ID;
	}

	mData.putUInt16(storage->getType());
	mData.putUInt16(storage->getFileSystemType());
	mData.putUInt16(storage->getAccessCapability());
	mData.putUInt64(storage->getMaxCapacity());
	mData.putUInt64(storage->getFreeSpace());
	mData.putUInt32(1024*1024*1024); // Free Space in Objects
	string.set(storage->getDescription());
	mData.putString(string);
	mData.putEmptyString();   // Volume Identifier

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetObjectPropsSupported() {
	MTPD("doGetObjectPropsSupported()\n");
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	MtpObjectFormat format = mRequest.getParameter(1);
	mDatabase->lockMutex();
	MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
	mData.putAUInt16(properties);
	delete properties;
	mDatabase->unlockMutex();
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetObjectHandles() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	MtpStorageID storageID = mRequest.getParameter(1);	  // 0xFFFFFFFF for all storage
	MtpObjectFormat format = mRequest.getParameter(2);	  // 0 for all formats
	MtpObjectHandle parent = mRequest.getParameter(3);	  // 0xFFFFFFFF for objects with no parent
															// 0x00000000 for all objects

	if (!hasStorage(storageID))
		return MTP_RESPONSE_INVALID_STORAGE_ID;

	MTPD("calling MtpDatabase->getObjectList()\n");
	mDatabase->lockMutex();
	MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
	mData.putAUInt32(handles);
	delete handles;
	mDatabase->unlockMutex();
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetNumObjects() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	MtpStorageID storageID = mRequest.getParameter(1);	  // 0xFFFFFFFF for all storage
	MtpObjectFormat format = mRequest.getParameter(2);	  // 0 for all formats
	MtpObjectHandle parent = mRequest.getParameter(3);	  // 0xFFFFFFFF for objects with no parent
															// 0x00000000 for all objects
	if (!hasStorage(storageID))
		return MTP_RESPONSE_INVALID_STORAGE_ID;

	mDatabase->lockMutex();
	int count = mDatabase->getNumObjects(storageID, format, parent);
	mDatabase->unlockMutex();
	if (count >= 0) {
		mResponse.setParameter(1, count);
		return MTP_RESPONSE_OK;
	} else {
		mResponse.setParameter(1, 0);
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	}
}

MtpResponseCode MtpServer::doGetObjectReferences() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);

	// FIXME - check for invalid object handle
	mDatabase->lockMutex();
	MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
	if (handles) {
		mData.putAUInt32(handles);
		delete handles;
	} else {
		MTPD("MtpServer::doGetObjectReferences putEmptyArray\n");
		mData.putEmptyArray();
	}
	mDatabase->unlockMutex();
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doSetObjectReferences() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpStorageID handle = mRequest.getParameter(1);

	MtpObjectHandleList* references = mData.getAUInt32();
	mDatabase->lockMutex();
	MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
	mDatabase->unlockMutex();
	delete references;
	return result;
}

MtpResponseCode MtpServer::doGetObjectPropValue() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectProperty property = mRequest.getParameter(2);
	MTPD("GetObjectPropValue %d %s\n", handle,
			MtpDebug::getObjectPropCodeName(property));

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->getObjectPropertyValue(handle, property, mData);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doSetObjectPropValue() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectProperty property = mRequest.getParameter(2);
	MTPD("SetObjectPropValue %d %s\n", handle,
			MtpDebug::getObjectPropCodeName(property));

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->setObjectPropertyValue(handle, property, mData);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doGetDevicePropValue() {
	MtpDeviceProperty property = mRequest.getParameter(1);
	MTPD("GetDevicePropValue %s\n",
			MtpDebug::getDevicePropCodeName(property));

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->getDevicePropertyValue(property, mData);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doSetDevicePropValue() {
	MtpDeviceProperty property = mRequest.getParameter(1);
	MTPD("SetDevicePropValue %s\n",
			MtpDebug::getDevicePropCodeName(property));

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->setDevicePropertyValue(property, mData);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doResetDevicePropValue() {
	MtpDeviceProperty property = mRequest.getParameter(1);
	MTPD("ResetDevicePropValue %s\n",
			MtpDebug::getDevicePropCodeName(property));

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->resetDeviceProperty(property);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doGetObjectPropList() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;

	MtpObjectHandle handle = mRequest.getParameter(1);
	// use uint32_t so we can support 0xFFFFFFFF
	uint32_t format = mRequest.getParameter(2);
	uint32_t property = mRequest.getParameter(3);
	int groupCode = mRequest.getParameter(4);
	int depth = mRequest.getParameter(5);
	MTPD("GetObjectPropList %d format: %s property: %x group: %d depth: %d\n",
			handle, MtpDebug::getFormatCodeName(format),
			property, groupCode, depth);

	mDatabase->lockMutex();
	MtpResponseCode res = mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
	mDatabase->unlockMutex();
	return res;
}

MtpResponseCode MtpServer::doGetObjectInfo() {
	MTPD("inside doGetObjectInfo()\n");
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectInfo info(handle);
	MTPD("calling mtpdatabase getObjectInfo()\n");
	mDatabase->lockMutex();
	MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
	mDatabase->unlockMutex();
	if (result == MTP_RESPONSE_OK) {
		char	date[20];

		mData.putUInt32(info.mStorageID);
		mData.putUInt16(info.mFormat);
		mData.putUInt16(info.mProtectionStatus);

		// if object is being edited the database size may be out of date
		uint32_t size = info.mCompressedSize;
		ObjectEdit* edit = getEditObject(handle);
		if (edit)
			size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize);
		mData.putUInt32(size);

		mData.putUInt16(info.mThumbFormat);
		mData.putUInt32(info.mThumbCompressedSize);
		mData.putUInt32(info.mThumbPixWidth);
		mData.putUInt32(info.mThumbPixHeight);
		mData.putUInt32(info.mImagePixWidth);
		mData.putUInt32(info.mImagePixHeight);
		mData.putUInt32(info.mImagePixDepth);
		mData.putUInt32(info.mParent);
		mData.putUInt16(info.mAssociationType);
		mData.putUInt32(info.mAssociationDesc);
		mData.putUInt32(info.mSequenceNumber);
		MTPD("info.mName: %s\n", info.mName);
		mData.putString(info.mName);
		mData.putEmptyString();	// date created
		formatDateTime(info.mDateModified, date, sizeof(date));
		mData.putString(date);   // date modified
		mData.putEmptyString();   // keywords
	}
	return result;
}

MtpResponseCode MtpServer::doGetObject() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpString pathBuf;
	int64_t fileLength;
	MtpObjectFormat format;
	MTPD("MtpServer::doGetObject calling getObjectFilePath\n");
	mDatabase->lockMutex();
	int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
	mDatabase->unlockMutex();
	if (result != MTP_RESPONSE_OK)
		return result;

	const char* filePath = (const char *)pathBuf;
	MTPD("filePath: %s\n", filePath);
	mtp_file_range  mfr;
	mfr.fd = open(filePath, O_RDONLY);
	if (mfr.fd < 0) {
		return MTP_RESPONSE_GENERAL_ERROR;
	}
	mfr.offset = 0;
	mfr.length = fileLength;
	MTPD("mfr.length: %lld\n", mfr.length);
	mfr.command = mRequest.getOperationCode();
	mfr.transaction_id = mRequest.getTransactionID();

	// then transfer the file
	int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
	MTPD("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
	close(mfr.fd);
	if (ret < 0) {
		if (errno == ECANCELED)
			return MTP_RESPONSE_TRANSACTION_CANCELLED;
		else
			return MTP_RESPONSE_GENERAL_ERROR;
	}
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetThumb() {
	MtpObjectHandle handle = mRequest.getParameter(1);
	size_t thumbSize;
	mDatabase->lockMutex();
	void* thumb = mDatabase->getThumbnail(handle, thumbSize);
	mDatabase->unlockMutex();
	if (thumb) {
		// send data
		mData.setOperationCode(mRequest.getOperationCode());
		mData.setTransactionID(mRequest.getTransactionID());
		mData.writeData(mFD, thumb, thumbSize);
		free(thumb);
		return MTP_RESPONSE_OK;
	} else {
		return MTP_RESPONSE_GENERAL_ERROR;
	}
}

MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	uint64_t offset;
	uint32_t length;
	offset = mRequest.getParameter(2);
	if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {
		// android extension with 64 bit offset
		uint64_t offset2 = mRequest.getParameter(3);
		offset = offset | (offset2 << 32);
		length = mRequest.getParameter(4);
	} else {
		// standard GetPartialObject
		length = mRequest.getParameter(3);
	}
	MtpString pathBuf;
	int64_t fileLength;
	MtpObjectFormat format;
	MTPD("MtpServer::doGetPartialObject calling getObjectFilePath\n");
	mDatabase->lockMutex();
	int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
	mDatabase->unlockMutex();
	if (result != MTP_RESPONSE_OK) {
		return result;
	}
	if (offset + length > (uint64_t)fileLength)
		length = fileLength - offset;

	const char* filePath = (const char *)pathBuf;
	mtp_file_range  mfr;
	mfr.fd = open(filePath, O_RDONLY);
	if (mfr.fd < 0) {
		return MTP_RESPONSE_GENERAL_ERROR;
	}
	mfr.offset = offset;
	mfr.length = length;
	mfr.command = mRequest.getOperationCode();
	mfr.transaction_id = mRequest.getTransactionID();
	mResponse.setParameter(1, length);

	// transfer the file
	int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
	MTPD("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
	close(mfr.fd);
	if (ret < 0) {
		if (errno == ECANCELED)
			return MTP_RESPONSE_TRANSACTION_CANCELLED;
		else
			return MTP_RESPONSE_GENERAL_ERROR;
	}
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doSendObjectInfo() {
	MTPD("MtpServer::doSendObjectInfo starting\n");
	MtpString path;
	MtpStorageID storageID = mRequest.getParameter(1);
	MtpStorage* storage = getStorage(storageID);
	MtpObjectHandle parent = mRequest.getParameter(2);
	if (!storage)
		return MTP_RESPONSE_INVALID_STORAGE_ID;

	// special case the root
	if (parent == MTP_PARENT_ROOT) {
		MTPD("MtpServer::doSendObjectInfo special case root\n");
		path = storage->getPath();
		parent = 0;
	} else {
		int64_t length;
		MtpObjectFormat format;
		MTPD("MtpServer::doSendObjectInfo calling getObjectFilePath\n");
		mDatabase->lockMutex();
		int result = mDatabase->getObjectFilePath(parent, path, length, format);
		mDatabase->unlockMutex();
		if (result != MTP_RESPONSE_OK) {
			return result;
		}
		if (format != MTP_FORMAT_ASSOCIATION)
			return MTP_RESPONSE_INVALID_PARENT_OBJECT;
	}

	// read only the fields we need
	mData.getUInt32();  // storage ID
	MtpObjectFormat format = mData.getUInt16();
	mData.getUInt16();  // protection status
	mSendObjectFileSize = mData.getUInt32();
	mData.getUInt16();  // thumb format
	mData.getUInt32();  // thumb compressed size
	mData.getUInt32();  // thumb pix width
	mData.getUInt32();  // thumb pix height
	mData.getUInt32();  // image pix width
	mData.getUInt32();  // image pix height
	mData.getUInt32();  // image bit depth
	mData.getUInt32();  // parent
	uint16_t associationType = mData.getUInt16();
	uint32_t associationDesc = mData.getUInt32();   // association desc
	mData.getUInt32();  // sequence number
	MtpStringBuffer name, created, modified;
	mData.getString(name);	// file name
	mData.getString(created);	  // date created
	mData.getString(modified);	 // date modified
	// keywords follow

	MTPD("name: %s format: %04X\n", (const char *)name, format);
	time_t modifiedTime;
	if (!parseDateTime(modified, modifiedTime)) {
		modifiedTime = 0;
	}
	if (path[path.size() - 1] != '/') {
		path += "/";
	}
	path += (const char *)name;

	// check space first
	if (mSendObjectFileSize > storage->getFreeSpace())
		return MTP_RESPONSE_STORAGE_FULL;
	uint64_t maxFileSize = storage->getMaxFileSize();
	// check storage max file size
	MTPD("maxFileSize: %ld\n", maxFileSize); 
	if (maxFileSize != 0) {
		// if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
		// is >= 0xFFFFFFFF
		if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
			return MTP_RESPONSE_OBJECT_TOO_LARGE;
	}

	MTPD("MtpServer::doSendObjectInfo path: %s parent: %d storageID: %08X\n", (const char*)path, parent, storageID);
	mDatabase->lockMutex();
	MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
			format, parent, storageID, mSendObjectFileSize, modifiedTime);
	mDatabase->unlockMutex();
	if (handle == kInvalidObjectHandle) {
		MTPE("MtpServer::doSendObjectInfo returning MTP_RESPONSE_GENERAL_ERROR, handle == kInvalidObjectHandle\n");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

  if (format == MTP_FORMAT_ASSOCIATION) {
		mode_t mask = umask(0);
		MTPD("MtpServer::doSendObjectInfo mkdir '%s'\n", (const char *)path);
		int ret = mkdir((const char *)path, mDirectoryPermission);
		umask(mask);
		if (ret && ret != -EEXIST) {
			MTPE("MtpServer::doSendObjectInfo returning MTP_RESPONSE_GENERAL_ERROR, ret && ret != -EEXIST\n");
			return MTP_RESPONSE_GENERAL_ERROR;
		}
		chown((const char *)path, getuid(), mFileGroup);
		tw_set_default_metadata((const char *)path);

		// SendObject does not get sent for directories, so call endSendObject here instead
		mDatabase->lockMutex();
		mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK);
		mDatabase->unlockMutex();
	} else {
		mSendObjectFilePath = path;
		// save the handle for the SendObject call, which should follow
		mSendObjectHandle = handle;
		mSendObjectFormat = format;
	}

	mResponse.setParameter(1, storageID);
	mResponse.setParameter(2, parent);
	mResponse.setParameter(3, handle);
	MTPD("MtpServer::doSendObjectInfo returning MTP_RESPONSE_OK\n");
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doSendObject() {
	if (!hasStorage())
		return MTP_RESPONSE_GENERAL_ERROR;
	MtpResponseCode result = MTP_RESPONSE_OK;
	mode_t mask;
	int ret = 0, initialData;

	if (mSendObjectHandle == kInvalidObjectHandle) {
		MTPE("Expected SendObjectInfo before SendObject");
		result = MTP_RESPONSE_NO_VALID_OBJECT_INFO;
		goto done;
	}

	// read the header, and possibly some data
	ret = mData.read(mFD);
	if (ret < MTP_CONTAINER_HEADER_SIZE) {
		MTPE("MTP_RESPONSE_GENERAL_ERROR\n");
		result = MTP_RESPONSE_GENERAL_ERROR;
		goto done;
	}
	initialData = ret - MTP_CONTAINER_HEADER_SIZE;

	mtp_file_range  mfr;
	mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC, 0640);
	if (mfr.fd < 0) {
		result = MTP_RESPONSE_GENERAL_ERROR;
		MTPE("fd error\n");
		goto done;
	}
	fchown(mfr.fd, getuid(), mFileGroup);
	// set permissions
	mask = umask(0);
	fchmod(mfr.fd, mFilePermission);
	umask(mask);

	if (initialData > 0)
		ret = write(mfr.fd, mData.getData(), initialData);

	if (mSendObjectFileSize - initialData > 0) {
		mfr.offset = initialData;
		if (mSendObjectFileSize == 0xFFFFFFFF) {
			// tell driver to read until it receives a short packet
			mfr.length = 0xFFFFFFFF;
		} else {
			mfr.length = mSendObjectFileSize - initialData;
		}

		MTPD("receiving %s\n", (const char *)mSendObjectFilePath);
		// transfer the file
		ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
	}
	close(mfr.fd);
	tw_set_default_metadata((const char *)mSendObjectFilePath);

	if (ret < 0) {
		unlink(mSendObjectFilePath);
		if (errno == ECANCELED)
			result = MTP_RESPONSE_TRANSACTION_CANCELLED;
		else {
		    	MTPD("errno: %d\n", errno);
			result = MTP_RESPONSE_GENERAL_ERROR;
		}
	}

done:
	// reset so we don't attempt to send the data back
	MTPD("MTP_RECEIVE_FILE returned %d\n", ret);
	mData.reset();
	mDatabase->lockMutex();
	mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
			result == MTP_RESPONSE_OK);
	mDatabase->unlockMutex();
	mSendObjectHandle = kInvalidObjectHandle;
	MTPD("result: %d\n", result);
	mSendObjectFormat = 0;
	return result;
}

static void deleteRecursive(const char* path) {
	char pathbuf[PATH_MAX];
	size_t pathLength = strlen(path);
	if (pathLength >= sizeof(pathbuf) - 1) {
		MTPE("path too long: %s\n", path);
	}
	strcpy(pathbuf, path);
	if (pathbuf[pathLength - 1] != '/') {
		pathbuf[pathLength++] = '/';
	}
	char* fileSpot = pathbuf + pathLength;
	int pathRemaining = sizeof(pathbuf) - pathLength - 1;

	DIR* dir = opendir(path);
	if (!dir) {
		MTPE("opendir %s failed: %s", path, strerror(errno));
		return;
	}

	struct dirent* entry;
	while ((entry = readdir(dir))) {
		const char* name = entry->d_name;

		// ignore "." and ".."
		if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
			continue;
		}

		int nameLength = strlen(name);
		if (nameLength > pathRemaining) {
			MTPE("path %s/%s too long\n", path, name);
			continue;
		}
		strcpy(fileSpot, name);

		int type = entry->d_type;
		struct stat st;
		if (lstat(pathbuf, &st)) {
			MTPE("Failed to lstat '%s'\n", pathbuf);
			continue;
		}
		if (st.st_mode & S_IFDIR) {
			deleteRecursive(pathbuf);
			rmdir(pathbuf);
		} else {
			unlink(pathbuf);
		}
	}
	closedir(dir);
}

static void deletePath(const char* path) {
	struct stat statbuf;
	if (stat(path, &statbuf) == 0) {
		if (S_ISDIR(statbuf.st_mode)) {
			deleteRecursive(path);
			rmdir(path);
		} else {
			unlink(path);
		}
	} else {
		MTPE("deletePath stat failed for %s: %s", path, strerror(errno));
	}
}

MtpResponseCode MtpServer::doDeleteObject() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectFormat format = mRequest.getParameter(2);
	// FIXME - support deleting all objects if handle is 0xFFFFFFFF
	// FIXME - implement deleting objects by format

	MtpString filePath;
	int64_t fileLength;
	MTPD("MtpServer::doDeleteObject calling getObjectFilePath\n");
	mDatabase->lockMutex();
	int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
	if (result == MTP_RESPONSE_OK) {
		MTPD("deleting %s", (const char *)filePath);
		result = mDatabase->deleteFile(handle);
		// Don't delete the actual files unless the database deletion is allowed
		if (result == MTP_RESPONSE_OK) {
			deletePath((const char *)filePath);
		}
	}
	mDatabase->unlockMutex();
	return result;
}

MtpResponseCode MtpServer::doGetObjectPropDesc() {
	MtpObjectProperty propCode = mRequest.getParameter(1);
	MtpObjectFormat format = mRequest.getParameter(2);
	MTPD("MtpServer::doGetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
										MtpDebug::getFormatCodeName(format));
	mDatabase->lockMutex();
	MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
	mDatabase->unlockMutex();
	if (!property) {
		MTPE("MtpServer::doGetObjectPropDesc propery not supported\n");
		return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
	}
	property->write(mData);
	delete property;
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetDevicePropDesc() {
	MtpDeviceProperty propCode = mRequest.getParameter(1);
	MTPD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
	mDatabase->lockMutex();
	MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
	mDatabase->unlockMutex();
	if (!property) {
		MTPE("MtpServer::doGetDevicePropDesc property not supported\n");
		return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
	}
	property->write(mData);
	delete property;
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doSendPartialObject() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	MtpObjectHandle handle = mRequest.getParameter(1);
	uint64_t offset = mRequest.getParameter(2);
	uint64_t offset2 = mRequest.getParameter(3);
	offset = offset | (offset2 << 32);
	uint32_t length = mRequest.getParameter(4);

	ObjectEdit* edit = getEditObject(handle);
	if (!edit) {
		MTPE("object not open for edit in doSendPartialObject");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	// can't start writing past the end of the file
	if (offset > edit->mSize) {
		MTPE("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize);
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	const char* filePath = (const char *)edit->mPath;
	MTPD("receiving partial %s %lld %lld\n", filePath, offset, length);

	// read the header, and possibly some data
	int ret = mData.read(mFD);
	if (ret < MTP_CONTAINER_HEADER_SIZE)
		return MTP_RESPONSE_GENERAL_ERROR;
	int initialData = ret - MTP_CONTAINER_HEADER_SIZE;

	if (initialData > 0) {
		ret = write(edit->mFD, mData.getData(), initialData);
		offset += initialData;
		length -= initialData;
	}

	if (length > 0) {
		mtp_file_range  mfr;
		mfr.fd = edit->mFD;
		mfr.offset = offset;
		mfr.length = length;

		// transfer the file
		ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
		MTPD("MTP_RECEIVE_FILE returned %d", ret);
	}
	if (ret < 0) {
		mResponse.setParameter(1, 0);
		if (errno == ECANCELED)
			return MTP_RESPONSE_TRANSACTION_CANCELLED;
		else
			return MTP_RESPONSE_GENERAL_ERROR;
	}

	// reset so we don't attempt to send this back
	mData.reset();
	mResponse.setParameter(1, length);
	uint64_t end = offset + length;
	if (end > edit->mSize) {
		edit->mSize = end;
	}
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doTruncateObject() {
	MtpObjectHandle handle = mRequest.getParameter(1);
	ObjectEdit* edit = getEditObject(handle);
	if (!edit) {
		MTPE("object not open for edit in doTruncateObject");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	uint64_t offset = mRequest.getParameter(2);
	uint64_t offset2 = mRequest.getParameter(3);
	offset |= (offset2 << 32);
	if (ftruncate(edit->mFD, offset) != 0) {
		return MTP_RESPONSE_GENERAL_ERROR;
	} else {
		edit->mSize = offset;
		return MTP_RESPONSE_OK;
	}
}

MtpResponseCode MtpServer::doBeginEditObject() {
	MtpObjectHandle handle = mRequest.getParameter(1);
	if (getEditObject(handle)) {
		MTPE("object already open for edit in doBeginEditObject");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	MtpString path;
	int64_t fileLength;
	MtpObjectFormat format;
	MTPD("MtpServer::doBeginEditObject calling getObjectFilePath\n");
	mDatabase->lockMutex();
	int result = mDatabase->getObjectFilePath(handle, path, fileLength, format);
	mDatabase->unlockMutex();
	if (result != MTP_RESPONSE_OK)
		return result;

	int fd = open((const char *)path, O_RDWR | O_EXCL);
	if (fd < 0) {
		MTPE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno);
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	addEditObject(handle, path, fileLength, format, fd);
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doEndEditObject() {
	MtpObjectHandle handle = mRequest.getParameter(1);
	ObjectEdit* edit = getEditObject(handle);
	if (!edit) {
		MTPE("object not open for edit in doEndEditObject");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	commitEdit(edit);
	removeEditObject(handle);
	return MTP_RESPONSE_OK;
}
