/*
 * 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 <algorithm>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <chrono>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/time.h>

#define LOG_TAG "MtpServer"

#include "MtpDebug.h"
#include "mtp_MtpDatabase.hpp"
#include "MtpDescriptors.h"
#include "MtpDevHandle.h"
#include "MtpFfsCompatHandle.h"
#include "MtpFfsHandle.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpServer.h"
#include "MtpStorage.h"
#include "MtpStringBuffer.h"

static const int SN_EVENT_LOG_ID = 0x534e4554;

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_DEVICE_PROP_CHANGED,
};

MtpServer::MtpServer(IMtpDatabase* database, int controlFd, bool ptp,
					const char *deviceInfoManufacturer,
					const char *deviceInfoModel,
					const char *deviceInfoDeviceVersion,
					const char *deviceInfoSerialNumber)
	:	mDatabase(database),
		mPtp(ptp),
		mDeviceInfoManufacturer(deviceInfoManufacturer),
		mDeviceInfoModel(deviceInfoModel),
		mDeviceInfoDeviceVersion(deviceInfoDeviceVersion),
		mDeviceInfoSerialNumber(deviceInfoSerialNumber),
		mSessionID(0),
		mSessionOpen(false),
		mSendObjectHandle(kInvalidObjectHandle),
		mSendObjectFormat(0),
		mSendObjectFileSize(0),
		mSendObjectModifiedTime(0)
{
	bool ffs_ok = access(FFS_MTP_EP0, W_OK) == 0;
	if (ffs_ok) {
		bool aio_compat = android::base::GetBoolProperty("sys.usb.ffs.aio_compat", false);
		mHandle = aio_compat ? new MtpFfsCompatHandle(controlFd) : new MtpFfsHandle(controlFd);
		mHandle->writeDescriptors(mPtp);
	} else {
		mHandle = new MtpDevHandle(controlFd);
	}
}

MtpServer::~MtpServer() {
}

void MtpServer::addStorage(MtpStorage* storage) {
	std::lock_guard<std::mutex> lg(mMutex);
	mDatabase->createDB(storage, storage->getStorageID());
	mStorages.push_back(storage);
	sendStoreAdded(storage->getStorageID());
}

void MtpServer::removeStorage(MtpStorage* storage) {
	std::lock_guard<std::mutex> lg(mMutex);
	auto iter = std::find(mStorages.begin(), mStorages.end(), storage);
	if (iter != mStorages.end()) {
		sendStoreRemoved(storage->getStorageID());
		mStorages.erase(iter);
	}
}

MtpStorage* MtpServer::getStorage(MtpStorageID id) {
	if (id == 0)
		return mStorages[0];
	for (MtpStorage *storage : mStorages) {
		if (storage->getStorageID() == id)
			return storage;
	}
	return nullptr;
}

bool MtpServer::hasStorage(MtpStorageID id) {
	if (id == 0 || id == 0xFFFFFFFF)
		return mStorages.size() > 0;
	return (getStorage(id) != nullptr);
}

void MtpServer::run() {
	if (mHandle->start(mPtp)) {
		MTPE("Failed to start usb driver!\n");
		mHandle->close();
        int controlFd = open(FFS_MTP_EP0, O_RDWR);
        bool ffs_ok = access(FFS_MTP_EP0, W_OK) == 0;
        if (ffs_ok) {
            bool aio_compat = android::base::GetBoolProperty("sys.usb.ffs.aio_compat", false);
            mHandle = aio_compat ? new MtpFfsCompatHandle(controlFd) : new MtpFfsHandle(controlFd);
            mHandle->writeDescriptors(mPtp);
        } else {
            mHandle = new MtpDevHandle(controlFd);
        }
		return;
	}

	while (1) {
		int ret = mRequest.read(mHandle);
		if (ret < 0) {
			MTPE("request read returned %d, errno: %d", ret, errno);
			if (errno == ECANCELED) {
				// return to top of loop and wait for next command
				continue;
			}
			break;
		}
		MtpOperationCode operation = mRequest.getOperationCode();
		MtpTransactionID transaction = mRequest.getTransactionID();

		MTPD("operation: %s\n", MtpDebug::getOperationCodeName(operation));
		// 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(mHandle);
			if (ret < 0) {
				MTPE("data read returned %d, errno: %d", ret, errno);
				if (errno == ECANCELED) {
					// return to top of loop and wait for next command
					continue;
				}
				break;
			}
			MTPD("received data:");
		} else {
			mData.reset();
		}

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

			mResponse.setTransactionID(transaction);
			MTPD("sending response %04X", mResponse.getResponseCode());
			ret = mResponse.write(mHandle);
			const int savedErrno = errno;
			if (ret < 0) {
				MTPE("request write returned %d, errno: %d", ret, errno);
				if (savedErrno == ECANCELED) {
					// return to top of loop and wait for next command
					continue;
				}
				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();

	mHandle->close();
}

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

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

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

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

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

void MtpServer::sendDevicePropertyChanged(MtpDeviceProperty property) {
	MTPD("MtpServer::sendDevicePropertyChanged %d\n", property);
	sendEvent(MTP_EVENT_DEVICE_PROP_CHANGED, property);
}

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

void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
	if (mSessionOpen) {
		mEvent.setEventCode(code);
		mEvent.setTransactionID(mRequest.getTransactionID());
		mEvent.setParameter(1, param1);
		if (mEvent.write(mHandle))
			MTPE("Mtp send event failed: %s\n", strerror(errno));
	}
}

void MtpServer::addEditObject(MtpObjectHandle handle, MtpStringBuffer& path,
		uint64_t size, MtpObjectFormat format, int fd) {
	ObjectEdit*  edit = new ObjectEdit(handle, path, size, format, fd);
	mObjectEditList.push_back(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 nullptr;
}

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.erase(mObjectEditList.begin() + i);
			return;
		}
	}
	MTPE("ObjectEdit not found in removeEditObject");
}

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


bool MtpServer::handleRequest() {
	std::lock_guard<std::mutex> lg(mMutex);

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

	mResponse.reset();

	if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) {
		mSendObjectHandle = kInvalidObjectHandle;
		mSendObjectFormat = 0;
		mSendObjectModifiedTime = 0;
	}

	int containertype = mRequest.getContainerType();
	if (containertype != MTP_CONTAINER_TYPE_COMMAND) {
		MTPE("wrong container type %d", containertype);
		return false;
	}

	MTPD("got command %s (%x)\n", MtpDebug::getOperationCodeName(operation), operation);

	switch (operation) {
		case MTP_OPERATION_GET_DEVICE_INFO:
			response = doGetDeviceInfo();
			break;
		case MTP_OPERATION_OPEN_SESSION:
			response = doOpenSession();
			break;
		case MTP_OPERATION_RESET_DEVICE:
		case MTP_OPERATION_CLOSE_SESSION:
			response = doCloseSession();
			break;
		case MTP_OPERATION_GET_STORAGE_IDS:
			response = doGetStorageIDs();
			break;
		 case MTP_OPERATION_GET_STORAGE_INFO:
			response = doGetStorageInfo();
			break;
		case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED:
			response = doGetObjectPropsSupported();
			break;
		case MTP_OPERATION_GET_OBJECT_HANDLES:
			response = doGetObjectHandles();
			break;
		case MTP_OPERATION_GET_NUM_OBJECTS:
			response = doGetNumObjects();
			break;
		case MTP_OPERATION_GET_OBJECT_REFERENCES:
			response = doGetObjectReferences();
			break;
		case MTP_OPERATION_SET_OBJECT_REFERENCES:
			response = doSetObjectReferences();
			break;
		case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
			response = doGetObjectPropValue();
			break;
		case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
			response = doSetObjectPropValue();
			break;
		case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
			response = doGetDevicePropValue();
			break;
		case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
			response = doSetDevicePropValue();
			break;
		case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
			response = doResetDevicePropValue();
			break;
		case MTP_OPERATION_GET_OBJECT_PROP_LIST:
			response = doGetObjectPropList();
			break;
		case MTP_OPERATION_GET_OBJECT_INFO:
			response = doGetObjectInfo();
			break;
		case MTP_OPERATION_GET_OBJECT:
			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:
			response = doSendObjectInfo();
			break;
		case MTP_OPERATION_SEND_OBJECT:
			response = doSendObject();
			break;
		case MTP_OPERATION_DELETE_OBJECT:
			response = doDeleteObject();
			break;
		case MTP_OPERATION_COPY_OBJECT:
			response = doCopyObject();
			break;
		case MTP_OPERATION_MOVE_OBJECT:
			response = doMoveObject();
			break;
		case MTP_OPERATION_GET_OBJECT_PROP_DESC:
			response = doGetObjectPropDesc();
			break;
		case MTP_OPERATION_GET_DEVICE_PROP_DESC:
			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 (%x)",
					MtpDebug::getOperationCodeName(operation), 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;

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

	// fill in device info
	mData.putUInt16(MTP_STANDARD_VERSION);
	if (mPtp) {
		mData.putUInt32(0);
	} else {
		// MTP Vendor Extension ID
		mData.putUInt32(6);
	}
	mData.putUInt16(MTP_STANDARD_VERSION);
	if (mPtp) {
		// no extensions
		string.set("");
	} else {
		// MTP extensions
		string.set("microsoft.com: 1.0; android.com: 1.0;");
	}
	mData.putString(string); // MTP Extensions
	mData.putUInt16(0); //Functional Mode
	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

	mData.putString(mDeviceInfoManufacturer); // Manufacturer
	mData.putString(mDeviceInfoModel); // Model
	mData.putString(mDeviceInfoDeviceVersion); // Device Version
	mData.putString(mDeviceInfoSerialNumber); // 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;
	}
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;

	mSessionID = mRequest.getParameter(1);
	mSessionOpen = true;

	return MTP_RESPONSE_OK;
}

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

MtpResponseCode MtpServer::doGetStorageIDs() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;

	int count = mStorages.size();
	mData.putUInt32(count);
	for (int i = 0; i < count; i++)
		mData.putUInt32(mStorages[i]->getStorageID());

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetStorageInfo() {
	MtpStringBuffer   string;

	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;

	MtpStorageID id = mRequest.getParameter(1);
	MtpStorage* storage = getStorage(id);
	if (!storage)
		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() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectFormat format = mRequest.getParameter(1);
	MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
	mData.putAUInt16(properties);
	delete properties;
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetObjectHandles() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (mRequest.getParameterCount() < 3)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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;

	MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
	if (handles == NULL)
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	mData.putAUInt32(handles);
	delete handles;
	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doGetNumObjects() {
	if (!mSessionOpen)
		return MTP_RESPONSE_SESSION_NOT_OPEN;
	if (mRequest.getParameterCount() < 3)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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;

	int count = mDatabase->getNumObjects(storageID, format, parent);
	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;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);

	// FIXME - check for invalid object handle
	MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
	if (handles) {
		mData.putAUInt32(handles);
		delete handles;
	} else {
		mData.putEmptyArray();
	}
	return MTP_RESPONSE_OK;
}

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

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

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

	return mDatabase->getObjectPropertyValue(handle, property, mData);
}

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

	return mDatabase->setObjectPropertyValue(handle, property, mData);
}

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

	return mDatabase->getDevicePropertyValue(property, mData);
}

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

	return mDatabase->setDevicePropertyValue(property, mData);
}

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

	return mDatabase->resetDeviceProperty(property);
}

MtpResponseCode MtpServer::doGetObjectPropList() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	if (mRequest.getParameterCount() < 5)
		return MTP_RESPONSE_INVALID_PARAMETER;

	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: %s group: %d depth: %d\n",
			handle, MtpDebug::getFormatCodeName(format),
			MtpDebug::getObjectPropCodeName(property), groupCode, depth);

	return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
}

MtpResponseCode MtpServer::doGetObjectInfo() {
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectInfo info(handle);
	MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
	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);
		mData.putString(info.mName);
		formatDateTime(info.mDateCreated, date, sizeof(date));
		mData.putString(date);	 // 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;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpStringBuffer pathBuf;
	int64_t fileLength;
	MtpObjectFormat format;
	int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
	if (result != MTP_RESPONSE_OK)
		return result;

	auto start = std::chrono::steady_clock::now();

	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 = 0;
	mfr.length = fileLength;
	mfr.command = mRequest.getOperationCode();
	mfr.transaction_id = mRequest.getTransactionID();

	// then transfer the file
	int ret = mHandle->sendFile(mfr);
	if (ret < 0) {
		MTPE("Mtp send file got error %s", strerror(errno));
		if (errno == ECANCELED) {
			result = MTP_RESPONSE_TRANSACTION_CANCELLED;
		} else {
			result = MTP_RESPONSE_GENERAL_ERROR;
		}
	} else {
		result = MTP_RESPONSE_OK;
	}

	auto end = std::chrono::steady_clock::now();
	std::chrono::duration<double> diff = end - start;
	struct stat sstat;
	fstat(mfr.fd, &sstat);
	uint64_t finalsize = sstat.st_size;
	MTPD("Sent a file over MTP. Time: %f s, Size: %" PRIu64 ", Rate: %f bytes/s",
			diff.count(), finalsize, ((double) finalsize) / diff.count());
	closeObjFd(mfr.fd, filePath);
	return result;
}

MtpResponseCode MtpServer::doGetThumb() {
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);
	size_t thumbSize;
	void* thumb = mDatabase->getThumbnail(handle, thumbSize);
	if (thumb) {
		// send data
		mData.setOperationCode(mRequest.getOperationCode());
		mData.setTransactionID(mRequest.getTransactionID());
		mData.writeData(mHandle, 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) {
		// MTP_OPERATION_GET_PARTIAL_OBJECT_64 takes 4 arguments
		if (mRequest.getParameterCount() < 4)
			return MTP_RESPONSE_INVALID_PARAMETER;

		// android extension with 64 bit offset
		uint64_t offset2 = mRequest.getParameter(3);
		offset = offset | (offset2 << 32);
		length = mRequest.getParameter(4);
	} else {
		// MTP_OPERATION_GET_PARTIAL_OBJECT takes 3 arguments
		if (mRequest.getParameterCount() < 3)
			return MTP_RESPONSE_INVALID_PARAMETER;

		// standard GetPartialObject
		length = mRequest.getParameter(3);
	}
	MtpStringBuffer pathBuf;
	int64_t fileLength;
	MtpObjectFormat format;
	int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
	if (result != MTP_RESPONSE_OK)
		return result;
	if (offset + length > (uint64_t)fileLength)
		length = fileLength - offset;

	const char* filePath = (const char *)pathBuf;
	MTPD("sending partial %s\n %" PRIu64 " %" PRIu32, filePath, offset, length);
	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 = mHandle->sendFile(mfr);
	MTPD("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
	result = MTP_RESPONSE_OK;
	if (ret < 0) {
		if (errno == ECANCELED)
			result = MTP_RESPONSE_TRANSACTION_CANCELLED;
		else
			result = MTP_RESPONSE_GENERAL_ERROR;
	}
	closeObjFd(mfr.fd, filePath);
	return result;
}

MtpResponseCode MtpServer::doSendObjectInfo() {
	MtpStringBuffer path;
	uint16_t temp16;
	uint32_t temp32;

	if (mRequest.getParameterCount() < 2)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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) {
		path.set(storage->getPath());
		parent = 0;
	} else {
		int64_t length;
		MtpObjectFormat format;
		int result = mDatabase->getObjectFilePath(parent, path, length, format);
		if (result != MTP_RESPONSE_OK)
			return result;
		if (format != MTP_FORMAT_ASSOCIATION)
			return MTP_RESPONSE_INVALID_PARENT_OBJECT;
	}

	// read only the fields we need
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // storage ID
	if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectFormat format = temp16;
	if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;  // protection status
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
	mSendObjectFileSize = temp32;
	if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb format
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb compressed size
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb pix width
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb pix height
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image pix width
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image pix height
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image bit depth
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // parent
	if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
	if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // sequence number
	MtpStringBuffer name, created, modified;
	if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER;	  // file name
	if (name.isEmpty()) {
		MTPE("empty name");
		return MTP_RESPONSE_INVALID_PARAMETER;
	}
	if (!mData.getString(created)) return MTP_RESPONSE_INVALID_PARAMETER;	   // date created
	if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER;	   // date modified
	// keywords follow

	MTPD("name: %s format: %04X\n", (const char *)name, format);
	time_t modifiedTime;
	if (!parseDateTime(modified, modifiedTime))
		modifiedTime = 0;

	if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0) ||
		(strcmp(name, "/") == 0) || (strcmp(basename(name), name) != 0)) {
		char errMsg[80];

		sprintf(errMsg, "Invalid name: %s", (const char *) name);
		ALOGE("%s (b/130656917)", errMsg);
		android_errorWriteWithInfoLog(SN_EVENT_LOG_ID, "130656917", -1, errMsg,
										strlen(errMsg));

		return MTP_RESPONSE_INVALID_PARAMETER;
	}
	if (path[path.size() - 1] != '/')
		path.append("/");
	path.append(basename(name));

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

	MTPD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
	uint64_t size = 0; // TODO: this needs to be implemented
	time_t modified_time = 0; // TODO: this needs to be implemented
	MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, format,
			parent, storageID, size, modified_time);
	if (handle == kInvalidObjectHandle) {
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	if (format == MTP_FORMAT_ASSOCIATION) {
		int ret = makeFolder((const char *)path);
		if (ret)
			return MTP_RESPONSE_GENERAL_ERROR;

		// SendObject does not get sent for directories, so call endSendObject here instead
		mDatabase->endSendObject((const char*)path, handle, format, MTP_RESPONSE_OK);
	}
	mSendObjectFilePath = path;
	// save the handle for the SendObject call, which should follow
	mSendObjectHandle = handle;
	mSendObjectFormat = format;
	mSendObjectModifiedTime = modifiedTime;

	mResponse.setParameter(1, storageID);
	mResponse.setParameter(2, parent);
	mResponse.setParameter(3, handle);

	return MTP_RESPONSE_OK;
}

MtpResponseCode MtpServer::doMoveObject() {
	if (!hasStorage())
		return MTP_RESPONSE_GENERAL_ERROR;
	if (mRequest.getParameterCount() < 3)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle objectHandle = mRequest.getParameter(1);
	MtpStorageID storageID = mRequest.getParameter(2);
	MtpStorage* storage = getStorage(storageID);
	MtpObjectHandle parent = mRequest.getParameter(3);
	if (!storage)
		return MTP_RESPONSE_INVALID_STORAGE_ID;
	MtpStringBuffer path;
	MtpResponseCode result;

	MtpStringBuffer fromPath;
	int64_t fileLength;
	MtpObjectFormat format;
	MtpObjectInfo info(objectHandle);
	result = mDatabase->getObjectInfo(objectHandle, info);
	if (result != MTP_RESPONSE_OK)
		return result;
	result = mDatabase->getObjectFilePath(objectHandle, fromPath, fileLength, format);
	if (result != MTP_RESPONSE_OK)
		return result;

	// special case the root
	if (parent == 0) {
		path.set(storage->getPath());
	} else {
		int64_t parentLength;
		MtpObjectFormat parentFormat;
		result = mDatabase->getObjectFilePath(parent, path, parentLength, parentFormat);
		if (result != MTP_RESPONSE_OK)
			return result;
		if (parentFormat != MTP_FORMAT_ASSOCIATION)
			return MTP_RESPONSE_INVALID_PARENT_OBJECT;
	}

	if (path[path.size() - 1] != '/')
		path.append("/");
	path.append(info.mName);

	result = mDatabase->beginMoveObject(objectHandle, parent, storageID);
	if (result != MTP_RESPONSE_OK)
		return result;

	if (info.mStorageID == storageID) {
		MTPD("Moving file from %s to %s", (const char*)fromPath, (const char*)path);
		if (renameTo(fromPath, path)) {
			PLOG(ERROR) << "rename() failed from " << fromPath << " to " << path;
			result = MTP_RESPONSE_GENERAL_ERROR;
		}
	} else {
		MTPD("Moving across storages from %s to %s", (const char*)fromPath, (const char*)path);
		if (format == MTP_FORMAT_ASSOCIATION) {
			int ret = makeFolder((const char *)path);
			ret += copyRecursive(fromPath, path);
			if (ret) {
				result = MTP_RESPONSE_GENERAL_ERROR;
			} else {
				deletePath(fromPath);
			}
		} else {
			if (copyFile(fromPath, path)) {
				result = MTP_RESPONSE_GENERAL_ERROR;
			} else {
				deletePath(fromPath);
			}
		}
	}

	// If the move failed, undo the database change
	mDatabase->endMoveObject(info.mParent, parent, info.mStorageID, storageID, objectHandle,
			result == MTP_RESPONSE_OK);

	return result;
}

MtpResponseCode MtpServer::doCopyObject() {
	if (!hasStorage())
		return MTP_RESPONSE_GENERAL_ERROR;
	MtpResponseCode result = MTP_RESPONSE_OK;
	if (mRequest.getParameterCount() < 3)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle objectHandle = mRequest.getParameter(1);
	MtpStorageID storageID = mRequest.getParameter(2);
	MtpStorage* storage = getStorage(storageID);
	MtpObjectHandle parent = mRequest.getParameter(3);
	if (!storage)
		return MTP_RESPONSE_INVALID_STORAGE_ID;
	MtpStringBuffer path;

	MtpStringBuffer fromPath;
	int64_t fileLength;
	MtpObjectFormat format;
	MtpObjectInfo info(objectHandle);
	result = mDatabase->getObjectInfo(objectHandle, info);
	if (result != MTP_RESPONSE_OK)
		return result;
	result = mDatabase->getObjectFilePath(objectHandle, fromPath, fileLength, format);
	if (result != MTP_RESPONSE_OK)
		return result;

	// special case the root
	if (parent == 0) {
		path.set(storage->getPath());
	} else {
		int64_t parentLength;
		MtpObjectFormat parentFormat;
		result = mDatabase->getObjectFilePath(parent, path, parentLength, parentFormat);
		if (result != MTP_RESPONSE_OK)
			return result;
		if (parentFormat != MTP_FORMAT_ASSOCIATION)
			return MTP_RESPONSE_INVALID_PARENT_OBJECT;
	}

	// check space first
	if ((uint64_t) fileLength > storage->getFreeSpace())
		return MTP_RESPONSE_STORAGE_FULL;

	if (path[path.size() - 1] != '/')
		path.append("/");
	path.append(info.mName);

	MtpObjectHandle handle = mDatabase->beginCopyObject(objectHandle, parent, storageID);
	if (handle == kInvalidObjectHandle) {
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	MTPD("Copying file from %s to %s", (const char*)fromPath, (const char*)path);
	if (format == MTP_FORMAT_ASSOCIATION) {
		int ret = makeFolder((const char *)path);
		ret += copyRecursive(fromPath, path);
		if (ret) {
			result = MTP_RESPONSE_GENERAL_ERROR;
		}
	} else {
		if (copyFile(fromPath, path)) {
			result = MTP_RESPONSE_GENERAL_ERROR;
		}
	}

	mDatabase->endCopyObject(handle, result);
	mResponse.setParameter(1, handle);
	return result;
}

MtpResponseCode MtpServer::doSendObject() {
	if (!hasStorage())
		return MTP_RESPONSE_GENERAL_ERROR;
	MtpResponseCode result = MTP_RESPONSE_OK;
	mode_t mask;
	int ret, initialData;
	bool isCanceled = false;
	struct stat sstat = {};

	auto start = std::chrono::steady_clock::now();

	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(mHandle);
	if (ret < MTP_CONTAINER_HEADER_SIZE) {
		result = MTP_RESPONSE_GENERAL_ERROR;
		goto done;
	}
	initialData = ret - MTP_CONTAINER_HEADER_SIZE;

	if (mSendObjectFormat == MTP_FORMAT_ASSOCIATION) {
		if (initialData != 0)
			MTPE("Expected folder size to be 0!");
		mSendObjectHandle = kInvalidObjectHandle;
		mSendObjectFormat = 0;
		mSendObjectModifiedTime = 0;
		return result;
	}

	mtp_file_range	mfr;
	mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
	if (mfr.fd < 0) {
		result = MTP_RESPONSE_GENERAL_ERROR;
		goto done;
	}
	fchown(mfr.fd, getuid(), FILE_GROUP);
	// set permissions
	mask = umask(0);
	fchmod(mfr.fd, FILE_PERM);
	umask(mask);

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

	if (ret < 0) {
		MTPE("failed to write initial data");
		result = MTP_RESPONSE_GENERAL_ERROR;
	} else {
		mfr.offset = initialData;
		if (mSendObjectFileSize == 0xFFFFFFFF) {
			// tell driver to read until it receives a short packet
			mfr.length = 0xFFFFFFFF;
		} else {
			mfr.length = mSendObjectFileSize - initialData;
		}

		mfr.command = 0;
		mfr.transaction_id = 0;

		// transfer the file
		ret = mHandle->receiveFile(mfr, mfr.length == 0 &&
				initialData == MTP_BUFFER_SIZE - MTP_CONTAINER_HEADER_SIZE);
		if ((ret < 0) && (errno == ECANCELED)) {
			isCanceled = true;
		}
	}

	if (mSendObjectModifiedTime) {
		struct timespec newTime[2];
		newTime[0].tv_nsec = UTIME_NOW;
		newTime[1].tv_sec = mSendObjectModifiedTime;
		newTime[1].tv_nsec = 0;
		if (futimens(mfr.fd, newTime) < 0) {
			MTPE("changing modified time failed, %s", strerror(errno));
		}
	}

	fstat(mfr.fd, &sstat);
	closeObjFd(mfr.fd, mSendObjectFilePath);

	if (ret < 0) {
		MTPE("Mtp receive file got error %s", strerror(errno));
		unlink(mSendObjectFilePath);
		if (isCanceled)
			result = MTP_RESPONSE_TRANSACTION_CANCELLED;
		else
			result = MTP_RESPONSE_GENERAL_ERROR;
	}

done:
	// reset so we don't attempt to send the data back
	mData.reset();

	mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, result == MTP_RESPONSE_OK);
	mSendObjectHandle = kInvalidObjectHandle;
	mSendObjectFormat = 0;
	mSendObjectModifiedTime = 0;

	auto end = std::chrono::steady_clock::now();
	std::chrono::duration<double> diff = end - start;
	uint64_t finalsize = sstat.st_size;
	MTPD("Got a file over MTP. Time: %fs, Size: %" PRIu64 ", Rate: %f bytes/s",
			diff.count(), finalsize, ((double) finalsize) / diff.count());
	return result;
}

MtpResponseCode MtpServer::doDeleteObject() {
	MTPD("In MtpServer::doDeleteObject\n");
	if (!hasStorage())
		return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);
	MtpObjectFormat format;
	// FIXME - support deleting all objects if handle is 0xFFFFFFFF
	// FIXME - implement deleting objects by format

	MtpStringBuffer filePath;
	int64_t fileLength;
	int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
	if (result != MTP_RESPONSE_OK)
		return result;

	// Don't delete the actual files unless the database deletion is allowed
	result = mDatabase->beginDeleteObject(handle);
	if (result != MTP_RESPONSE_OK)
		return result;

	bool success = deletePath((const char *)filePath);

	mDatabase->endDeleteObject(handle, success);
	return success ? result : MTP_RESPONSE_PARTIAL_DELETION;
}

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

MtpResponseCode MtpServer::doGetDevicePropDesc() {
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpDeviceProperty propCode = mRequest.getParameter(1);
	MTPD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
	MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
	if (!property)
		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;
	if (mRequest.getParameterCount() < 4)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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) {
		MTPD("writing past end of object, offset: %" PRIu64 ", edit->mSize: %" PRIu64,
			offset, edit->mSize);
		return MTP_RESPONSE_GENERAL_ERROR;
	}

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

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

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

	bool isCanceled = false;
	if (ret < 0) {
		MTPE("failed to write initial data");
	} else {
		mtp_file_range	mfr;
		mfr.fd = edit->mFD;
		mfr.offset = offset;
		mfr.length = length;
		mfr.command = 0;
		mfr.transaction_id = 0;

		// transfer the file
		ret = mHandle->receiveFile(mfr, mfr.length == 0 &&
				initialData == MTP_BUFFER_SIZE - MTP_CONTAINER_HEADER_SIZE);
		if ((ret < 0) && (errno == ECANCELED)) {
			isCanceled = true;
		}
	}
	if (ret < 0) {
		mResponse.setParameter(1, 0);
		if (isCanceled)
			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() {
	if (mRequest.getParameterCount() < 3)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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() {
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	MtpObjectHandle handle = mRequest.getParameter(1);
	if (getEditObject(handle)) {
		MTPE("object already open for edit in doBeginEditObject");
		return MTP_RESPONSE_GENERAL_ERROR;
	}

	MtpStringBuffer path;
	int64_t fileLength;
	MtpObjectFormat format;
	int result = mDatabase->getObjectFilePath(handle, path, fileLength, format);
	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() {
	if (mRequest.getParameterCount() < 1)
		return MTP_RESPONSE_INVALID_PARAMETER;
	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;
}
