/*
 * 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;
}
