/*
 * 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.
 *
 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
 */

#include "MtpDebug.h"
#include "MtpStorage.h"
#include "MtpDataPacket.h"
#include "MtpServer.h"
#include "MtpEventPacket.h"
#include "MtpDatabase.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <sys/inotify.h>
#include <fcntl.h>

#define WATCH_FLAGS ( IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY )

MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
		const char* description, uint64_t reserveSpace,
		bool removable, uint64_t maxFileSize, MtpServer* refserver)
	:	mStorageID(id),
		mFilePath(filePath),
		mDescription(description),
		mMaxCapacity(0),
		mMaxFileSize(maxFileSize),
		mReserveSpace(reserveSpace),
		mRemovable(removable),
		mServer(refserver)
{
	MTPI("MtpStorage id: %d path: %s\n", id, filePath);
	inotify_thread = 0;
	sendEvents = false;
	handleCurrentlySending = 0;
	use_mutex = true;
	if (pthread_mutex_init(&mtpMutex, NULL) != 0) {
		MTPE("Failed to init mtpMutex\n");
		use_mutex = false;
	}
	if (pthread_mutex_init(&inMutex, NULL) != 0) {
		MTPE("Failed to init inMutex\n");
		use_mutex = false;
	}
	
}

MtpStorage::~MtpStorage() {
	if (inotify_thread) {
		// TODO: what does this do? manpage says it does not kill the thread
		pthread_kill(inotify_thread, 0);
		for (std::map<int, Tree*>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
			inotify_rm_watch(inotify_fd, i->first);
		}
		close(inotify_fd);
	}
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		delete i->second;
	}
	if (use_mutex) {
		use_mutex = false;
		pthread_mutex_destroy(&mtpMutex);
		pthread_mutex_destroy(&inMutex);
	}
}

int MtpStorage::getType() const {
	return (mRemovable ? MTP_STORAGE_REMOVABLE_RAM :  MTP_STORAGE_FIXED_RAM);
}

int MtpStorage::getFileSystemType() const {
	return MTP_STORAGE_FILESYSTEM_HIERARCHICAL;
}

int MtpStorage::getAccessCapability() const {
	return MTP_STORAGE_READ_WRITE;
}

uint64_t MtpStorage::getMaxCapacity() {
	if (mMaxCapacity == 0) {
		struct statfs   stat;
		if (statfs(getPath(), &stat))
			return -1;
		mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize;
	}
	return mMaxCapacity;
}

uint64_t MtpStorage::getFreeSpace() {
	struct statfs   stat;
	if (statfs(getPath(), &stat))
		return -1;
	uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
	return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
}

const char* MtpStorage::getDescription() const {
	return (const char *)mDescription;
}

int MtpStorage::createDB() {
	std::string mtpParent = "";
	mtpstorageparent = getPath();
	// root directory is special: handle 0, parent 0, and empty path
	mtpmap[0] = new Tree(0, 0, "");
	MTPD("MtpStorage::createDB DONE\n");
	if (use_mutex) {
		MTPD("Starting inotify thread\n");
		sendEvents = true;
		inotify_thread = inotify();
	} else {
		MTPD("NOT starting inotify thread\n");
	}
	// for debugging and caching purposes, read the root dir already now
	readDir(mtpstorageparent, mtpmap[0]);
	// all other dirs are read on demand
	return 0;
}

MtpObjectHandleList* MtpStorage::getObjectList(MtpStorageID storageID, MtpObjectHandle parent) {
	MTPD("MtpStorage::getObjectList, parent: %u\n", parent);
	//append object id  (numerical #s) of database to int array
	MtpObjectHandleList* list = new MtpObjectHandleList();
	if (parent == MTP_PARENT_ROOT) {
		MTPD("parent == MTP_PARENT_ROOT\n");
		parent = 0;
	}

	if (mtpmap.find(parent) == mtpmap.end()) {
		MTPE("parent handle not found, returning empty list\n");
		return list;
	}

	Tree* tree = mtpmap[parent];
	if (!tree->wasAlreadyRead())
	{
		std::string path = getNodePath(tree);
		MTPD("reading directory on demand for tree %p (%u), path: %s\n", tree, tree->Mtpid(), path.c_str());
		readDir(path, tree);
	}

	mtpmap[parent]->getmtpids(list);
	MTPD("returning %u objects in %s.\n", list->size(), tree->getName().c_str());
	return list;
}

int MtpStorage::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
	struct stat st;
	uint64_t size = 0;
	MTPD("MtpStorage::getObjectInfo, handle: %u\n", handle);
	Node* node = findNode(handle);
	if (!node) {
		// Item is not on this storage device
		return -1;
	}
	
	info.mStorageID = getStorageID();
	MTPD("info.mStorageID: %u\n", info.mStorageID);
	info.mParent = node->getMtpParentId();
	MTPD("mParent: %u\n", info.mParent);
	// TODO: do we want to lstat again here, or read from the node properties?
	if (lstat(getNodePath(node).c_str(), &st) == 0)
		size = st.st_size;
	MTPD("size is: %llu\n", size);
	info.mCompressedSize = (size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size);
	info.mDateModified = st.st_mtime;
	if (S_ISDIR(st.st_mode)) {
		info.mFormat = MTP_FORMAT_ASSOCIATION;
	}
	else {
		info.mFormat = MTP_FORMAT_UNDEFINED;
	}
	info.mName = strdup(node->getName().c_str());
	MTPD("MtpStorage::getObjectInfo found, Exiting getObjectInfo()\n");
	return 0;
}

MtpObjectHandle MtpStorage::beginSendObject(const char* path,
											MtpObjectFormat format,
											MtpObjectHandle parent,
											uint64_t size,
											time_t modified) {
	MTPD("MtpStorage::beginSendObject(), path: '%s', parent: %u, format: %04x\n", path, parent, format);
	iter it = mtpmap.find(parent);
	if (it == mtpmap.end()) {
		MTPE("parent node not found, returning error\n");
		return kInvalidObjectHandle;
	}
	Tree* tree = it->second;

	std::string pathstr(path);
	size_t slashpos = pathstr.find_last_of('/');
	if (slashpos == std::string::npos) {
		MTPE("path has no slash, returning error\n");
		return kInvalidObjectHandle;
	}
	std::string parentdir = pathstr.substr(0, slashpos);
	std::string basename = pathstr.substr(slashpos + 1);
	if (parent != 0 && parentdir != getNodePath(tree)) {
		MTPE("beginSendObject into path '%s' but parent tree has path '%s', returning error\n", parentdir.c_str(), getNodePath(tree).c_str());
		return kInvalidObjectHandle;
	}

	MTPD("MtpStorage::beginSendObject() parentdir: %s basename: %s\n", parentdir.c_str(), basename.c_str());
	// note: for directories, the mkdir call is done later in MtpServer, here we just reserve a handle
	bool isDir = format == MTP_FORMAT_ASSOCIATION;
	Node* node = addNewNode(isDir, tree, basename);
	handleCurrentlySending = node->Mtpid();	// suppress inotify for this node while sending

	return node->Mtpid();
}

void MtpStorage::endSendObject(const char* path, MtpObjectHandle handle, MtpObjectFormat format, bool succeeded)
{
	Node* node = findNode(handle);
	if (!node)
		return;	// just ignore if this is for another storage

	node->addProperties(path, mStorageID);
	handleCurrentlySending = 0;
	// TODO: are we supposed to send an event about an upload by the initiator?
	if (sendEvents)
		mServer->sendObjectAdded(node->Mtpid());
}

int MtpStorage::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
	MTPD("MtpStorage::getObjectFilePath handle: %u\n", handle);
	Node* node = findNode(handle);
	if (!node)
	{
		// Item is not on this storage device
		return -1;
	}
	// TODO: do we want to lstat here, or just read the info from the node?
	struct stat st;
	if (lstat(getNodePath(node).c_str(), &st) == 0)
		outFileLength = st.st_size;
	else
		outFileLength = 0;
	outFilePath = getNodePath(node).c_str();
	MTPD("outFilePath: %s\n", outFilePath.string());
	outFormat = node->isDir() ? MTP_FORMAT_ASSOCIATION : MTP_FORMAT_UNDEFINED;
	return 0;
}

int MtpStorage::readDir(const std::string& path, Tree* tree)
{
	struct dirent *de;
	int storageID = getStorageID();
	MtpObjectHandle parent = tree->Mtpid();

	DIR *d = opendir(path.c_str());
	MTPD("reading dir '%s', parent handle %u\n", path.c_str(), parent);
	if (d == NULL) {
		MTPE("error opening '%s' -- error: %s\n", path.c_str(), strerror(errno));
		return -1;
	}
	// TODO: for refreshing dirs: capture old entries here
	while ((de = readdir(d)) != NULL) {
		// Because exfat-fuse causes issues with dirent, we will use stat
		// for some things that dirent should be able to do
		std::string item = path + "/" + de->d_name;
		struct stat st;
		if (lstat(item.c_str(), &st)) {
			MTPE("Error running lstat on '%s'\n", item.c_str());
			return -1;
		}
		// TODO: if we want to use this for refreshing dirs too, first find existing name and overwrite
		if (strcmp(de->d_name, ".") == 0)
			continue;
		if (strcmp(de->d_name, "..") == 0)
			continue;
		Node* node = addNewNode(st.st_mode & S_IFDIR, tree, de->d_name);
		node->addProperties(item, storageID);
		//if (sendEvents)
		//	mServer->sendObjectAdded(node->Mtpid());
		//	sending events here makes simple-mtpfs very slow, and it is probably the wrong thing to do anyway
	}
	closedir(d);
	// TODO: for refreshing dirs: remove entries that no longer exist (with their nodes)
	tree->setAlreadyRead(true);
	addInotify(tree);
	return 0;
}

int MtpStorage::deleteFile(MtpObjectHandle handle) {
	MTPD("MtpStorage::deleteFile handle: %u\n", handle);
	Node* node = findNode(handle);
	if (!node) {
		// Item is not on this storage device
		return -1;
	}
	MtpObjectHandle parent = node->getMtpParentId();
	Tree* tree = mtpmap[parent];
	if (!tree) {
		MTPE("parent tree for handle %u not found\n", parent);
		return -1;
	}
	if (node->isDir()) {
		MTPD("deleting tree from mtpmap: %u\n", handle);
		mtpmap.erase(handle);
	}

	MTPD("deleting handle: %u\n", handle);
	tree->deleteNode(handle);
	MTPD("deleted\n");
	return 0;
}

void MtpStorage::queryNodeProperties(std::vector<MtpStorage::PropEntry>& results, Node* node, uint32_t property, int groupCode, MtpStorageID storageID)
{
	MTPD("queryNodeProperties handle %u, path: %s\n", node->Mtpid(), getNodePath(node).c_str());
	PropEntry pe;
	pe.handle = node->Mtpid();
	pe.property = property;

	if (property == 0xffffffff)
	{
		// add all properties
		MTPD("MtpStorage::queryNodeProperties for all properties\n");
		std::vector<Node::mtpProperty> mtpprop = node->getMtpProps();
		for (size_t i = 0; i < mtpprop.size(); ++i) {
			pe.property = mtpprop[i].property;
			pe.datatype = mtpprop[i].dataType;
			pe.intvalue = mtpprop[i].valueInt;
			pe.strvalue = mtpprop[i].valueStr;
			results.push_back(pe);
		}
		return;
	}
	else if (property == 0)
	{
		// TODO: use groupCode
	}

	// single property
	// TODO: this should probably be moved to the Node class and/or merged with getObjectPropertyValue
	switch (property) {
//		case MTP_PROPERTY_OBJECT_FORMAT:
//			pe.datatype = MTP_TYPE_UINT16;
//			pe.intvalue = node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT);
//			break;

		case MTP_PROPERTY_STORAGE_ID:
			pe.datatype = MTP_TYPE_UINT32;
			pe.intvalue = storageID;
			break;

		case MTP_PROPERTY_PROTECTION_STATUS:
			pe.datatype = MTP_TYPE_UINT16;
			pe.intvalue = 0;
			break;

		case MTP_PROPERTY_OBJECT_SIZE:
		{
			pe.datatype = MTP_TYPE_UINT64;
			struct stat st;
			pe.intvalue = 0;
			if (lstat(getNodePath(node).c_str(), &st) == 0)
				pe.intvalue = st.st_size;
			break;
		}

		default:
		{
			const Node::mtpProperty& prop = node->getProperty(property);
			if (prop.property != property)
			{
				MTPD("queryNodeProperties: unknown property %x\n", property);
				return;
			}
			pe.datatype = prop.dataType;
			pe.intvalue = prop.valueInt;
			pe.strvalue = prop.valueStr;
			// TODO: all the special case stuff in MyMtpDatabase::getObjectPropertyValue is missing here
		}

	}
	results.push_back(pe);
}

int MtpStorage::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
	MTPD("MtpStorage::getObjectPropertyList handle: %u, format: %x, property: %x\n", handle, format, property);
	if (groupCode != 0)
	{
		MTPE("getObjectPropertyList: groupCode unsupported\n");
		return -1; // TODO: RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED
	}
	// TODO: support all the special stuff, like:
	// handle == 0 -> all objects at the root level
	// handle == 0xffffffff -> all objects (on all storages? how could we support that?)
	// format == 0 -> all formats, otherwise filter by ObjectFormatCode
	// property == 0xffffffff -> all properties except those with group code 0xffffffff
	// if property == 0 then use groupCode
	//   groupCode == 0 -> return Specification_By_Group_Unsupported
	// depth == 0xffffffff -> all objects incl. and below handle

	std::vector<PropEntry> results;

	if (handle == 0xffffffff) {
		// TODO: all object on all storages (needs a different design, result packet needs to be built by server instead of storage)
	} else if (handle == 0)	{
		// all objects at the root level
		Tree* root = mtpmap[0];
		MtpObjectHandleList list;
		root->getmtpids(&list);
		for (MtpObjectHandleList::iterator it = list.begin(); it != list.end(); ++it) {
			Node* node = root->findNode(*it);
			if (!node) {
				MTPE("BUG: node not found for root entry with handle %u\n", *it);
				break;
			}
			queryNodeProperties(results, node, property, groupCode, mStorageID);
		}
	} else {
		// single object
		Node* node = findNode(handle);
		if (!node) {
			// Item is not on this storage device
			return -1;
		}
		queryNodeProperties(results, node, property, groupCode, mStorageID);
	}

	MTPD("count: %u\n", results.size());
	packet.putUInt32(results.size());

	for (size_t i = 0; i < results.size(); ++i) {
		PropEntry& p = results[i];
		MTPD("handle: %u, propertyCode: %x = %s, datatype: %x, value: %llu\n",
				p.handle, p.property, MtpDebug::getObjectPropCodeName(p.property),
				p.datatype, p.intvalue);
		packet.putUInt32(p.handle);
		packet.putUInt16(p.property);
		packet.putUInt16(p.datatype);
		switch (p.datatype) {
			case MTP_TYPE_INT8:
				MTPD("MTP_TYPE_INT8\n");
				packet.putInt8(p.intvalue);
				break;
			case MTP_TYPE_UINT8:
				MTPD("MTP_TYPE_UINT8\n");
				packet.putUInt8(p.intvalue);
				break;
			case MTP_TYPE_INT16:
				MTPD("MTP_TYPE_INT16\n");
				packet.putInt16(p.intvalue);
				break;
			case MTP_TYPE_UINT16:
				MTPD("MTP_TYPE_UINT16\n");
				packet.putUInt16(p.intvalue);
				break;
			case MTP_TYPE_INT32:
				MTPD("MTP_TYPE_INT32\n");
				packet.putInt32(p.intvalue);
				break;
			case MTP_TYPE_UINT32:
				MTPD("MTP_TYPE_UINT32\n");
				packet.putUInt32(p.intvalue);
				break;
			case MTP_TYPE_INT64:
				MTPD("MTP_TYPE_INT64\n");
				packet.putInt64(p.intvalue);
				break;
			case MTP_TYPE_UINT64:
				MTPD("MTP_TYPE_UINT64\n");
				packet.putUInt64(p.intvalue);
				break;
			case MTP_TYPE_INT128:
				MTPD("MTP_TYPE_INT128\n");
				packet.putInt128(p.intvalue);
				break;
			case MTP_TYPE_UINT128:
				MTPD("MTP_TYPE_UINT128\n");
				packet.putUInt128(p.intvalue);
				break;
			case MTP_TYPE_STR:
				MTPD("MTP_TYPE_STR: %s\n", p.strvalue.c_str());
				packet.putString(p.strvalue.c_str());
				break;
			default:
				MTPE("bad or unsupported data type: %x in MyMtpDatabase::getObjectPropertyList", p.datatype);
				break;
		}
	}
	return 0;
}

int MtpStorage::renameObject(MtpObjectHandle handle, std::string newName) {
	MTPD("MtpStorage::renameObject, handle: %u, new name: '%s'\n", handle, newName.c_str());
	if (handle == MTP_PARENT_ROOT) {
		MTPE("parent == MTP_PARENT_ROOT, cannot rename root\n");
		return -1;
	} else {
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			Node* node = i->second->findNode(handle);
			if (node != NULL) {
				std::string oldName = getNodePath(node);
				std::string parentdir = oldName.substr(0, oldName.find_last_of('/'));
				std::string newFullName = parentdir + "/" + newName;
				MTPD("old: '%s', new: '%s'\n", oldName.c_str(), newFullName.c_str());
				if (rename(oldName.c_str(), newFullName.c_str()) == 0) {
					node->rename(newName);
					return 0;
				} else {
					MTPE("MtpStorage::renameObject failed, handle: %u, new name: '%s'\n", handle, newName.c_str());
					return -1;
				}
			}
		}
	}
	// handle not found on this storage
	return -1;
}

int MtpStorage::getObjectPropertyValue(MtpObjectHandle handle, MtpObjectProperty property, MtpStorage::PropEntry& pe) {
	Node *node;
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		node = i->second->findNode(handle);
		if (node != NULL) {
			const Node::mtpProperty& prop = node->getProperty(property);
			if (prop.property != property) {
				MTPD("getObjectPropertyValue: unknown property %x for handle %u\n", property, handle);
				return -1;
			}
			pe.datatype = prop.dataType;
			pe.intvalue = prop.valueInt;
			pe.strvalue = prop.valueStr;
			pe.handle = handle;
			pe.property = property;
			return 0;
		}
	}
	// handle not found on this storage
	return -1;
}

pthread_t MtpStorage::inotify(void) {
	pthread_t thread;
	ThreadPtr inotifyptr = &MtpStorage::inotify_t;
	PThreadPtr p = *(PThreadPtr*)&inotifyptr;
	pthread_create(&thread, NULL, p, this);
	return thread;
}

int MtpStorage::addInotify(Tree* tree) {
	std::string path = getNodePath(tree);
	MTPD("adding inotify for tree %x, dir: %s\n", tree, path.c_str());
	int wd = inotify_add_watch(inotify_fd, path.c_str(), WATCH_FLAGS);
	if (wd < 0) {
		MTPE("inotify_add_watch failed: %s\n", strerror(errno));
		return -1;
	}
	inotifymap[wd] = tree;
	return 0;
}

void MtpStorage::handleInotifyEvent(struct inotify_event* event)
{
	std::map<int, Tree*>::iterator it = inotifymap.find(event->wd);
	if (it == inotifymap.end()) {
		MTPE("Unable to locate inotify_wd: %i\n", event->wd);
		return;
	}
	Tree* tree = it->second;
	MTPD("inotify_t tree: %x '%s'\n", tree, tree->getName().c_str());
	Node* node = tree->findEntryByName(basename(event->name));
	if (node && node->Mtpid() == handleCurrentlySending) {
		MTPD("ignoring inotify event for currently uploading file, handle: %u\n", node->Mtpid());
		return;
	}
	if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) {
		if (event->mask & IN_ISDIR) {
			MTPD("inotify_t create is dir\n");
		} else {
			MTPD("inotify_t create is file\n");
		}
		if (node == NULL) {
			node = addNewNode(event->mask & IN_ISDIR, tree, event->name);
			std::string item = getNodePath(tree) + "/" + event->name;
			node->addProperties(item, getStorageID());
			mServer->sendObjectAdded(node->Mtpid());
		} else {
			MTPD("inotify_t item already exists.\n");
		}
		if (event->mask & IN_ISDIR) {
			// TODO: do we need to do anything here? probably not until someone reads from the dir...
		}
	} else if (event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) {
		if (event->mask & IN_ISDIR) {
			MTPD("inotify_t Directory %s deleted\n", event->name);
		} else {
			MTPD("inotify_t File %s deleted\n", event->name);
		}
		if (node)
		{
			if (event->mask & IN_ISDIR) {
				for (std::map<int, Tree*>::iterator it = inotifymap.begin(); it != inotifymap.end(); ++it) {
					if (it->second == node) {
						inotify_rm_watch(inotify_fd, it->first);
						MTPD("inotify_t removing watch on '%s'\n", getNodePath(it->second).c_str());
						inotifymap.erase(it->first);
						break;
					}

				}
			}
			MtpObjectHandle handle = node->Mtpid();
			deleteFile(handle);
			mServer->sendObjectRemoved(handle);
		} else {
			MTPD("inotify_t already removed.\n");
		}
	} else if (event->mask & IN_MODIFY) {
		MTPD("inotify_t item %s modified.\n", event->name);
		if (node != NULL) {
			uint64_t orig_size = node->getProperty(MTP_PROPERTY_OBJECT_SIZE).valueInt;
			struct stat st;
			uint64_t new_size = 0;
			if (lstat(getNodePath(node).c_str(), &st) == 0)
				new_size = (uint64_t)st.st_size;
			if (orig_size != new_size) {
				MTPD("size changed from %llu to %llu on mtpid: %u\n", orig_size, new_size, node->Mtpid());
				node->updateProperty(MTP_PROPERTY_OBJECT_SIZE, new_size, "", MTP_TYPE_UINT64);
				mServer->sendObjectUpdated(node->Mtpid());
			}
		} else {
			MTPE("inotify_t modified item not found\n");
		}
	} else if (event->mask & IN_DELETE_SELF || event->mask & IN_MOVE_SELF) {
		// TODO: is this always already handled by IN_DELETE for the parent dir?
	}
}

int MtpStorage::inotify_t(void) {
	#define EVENT_SIZE ( sizeof(struct inotify_event) )
	#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16) )
	char buf[EVENT_BUF_LEN];

	MTPD("inotify thread: inotify_init\n");
	inotify_fd = inotify_init();

	if (inotify_fd < 0) {
		MTPE("Can't run inotify for mtp server: %s\n", strerror(errno));
		return -1;
	}

	while (true) {
		int i = 0;
		int len = read(inotify_fd, buf, EVENT_BUF_LEN);

		if (len < 0) {
			if (errno == EINTR)
				continue;
			MTPE("inotify_t Can't read inotify events\n");
		}

		while (i < len) {
			struct inotify_event *event = (struct inotify_event *) &buf[i];
			if (event->len) {
				MTPD("inotify event: wd: %i, mask: %x, name: %s\n", event->wd, event->mask, event->name);
				lockMutex(1);
				handleInotifyEvent(event);
				unlockMutex(1);
			}
			i += EVENT_SIZE + event->len;
		}
	}

	for (std::map<int, Tree*>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
		inotify_rm_watch(inotify_fd, i->first);
	}
	close(inotify_fd);
	return 0;
}

Node* MtpStorage::findNodeByPath(const std::string& path) {
	MTPD("findNodeByPath: %s\n", path.c_str());
	std::string match = path.substr(0, mtpstorageparent.size());
	if (match != mtpstorageparent) {
		// not on this device
		MTPD("no match: %s is not on storage %s\n", match.c_str(), mtpstorageparent.c_str());
		return NULL;
	}

	// TODO: fix and test this
	std::string p = path.substr(mtpstorageparent.size()+1);	// cut off "/" after storage root too
	Tree* tree = mtpmap[0]; // start at storage root

	Node* node = NULL;
	while (!p.empty()) {
		size_t slashpos = p.find('/');
		std::string e;
		if (slashpos != std::string::npos) {
			e = p;
			p.clear();
		} else {
			e = p.substr(0, slashpos);
			p = p.substr(slashpos + 1);
		}
		MTPD("path element: %s, rest: %s\n", e.c_str(), p.c_str());
		node = tree->findEntryByName(e);
		if (!node) {
			MTPE("path element of %s not found: %s\n", path.c_str(), e.c_str());
			return NULL;
		}
		if (node->isDir())
			tree = static_cast<Tree*>(node);
		else if (!p.empty()) {
			MTPE("path element of %s is not a directory: %s node: %p\n", path.c_str(), e.c_str(), node);
			return NULL;
		}
	}
	MTPD("findNodeByPath: found node %p, handle: %u, name: %s\n", node, node->Mtpid(), node->getName().c_str());
	return node;
}

Node* MtpStorage::addNewNode(bool isDir, Tree* tree, const std::string& name)
{
	// global counter for new object handles
	static MtpObjectHandle mtpid = 0;

	++mtpid;
	MTPD("adding new %s node for %s, new handle: %u\n", isDir ? "dir" : "file", name.c_str(), mtpid);
	MtpObjectHandle parent = tree->Mtpid();
	MTPD("parent tree: %x, handle: %u, name: %s\n", tree, parent, tree->getName().c_str());
	Node* node;
	if (isDir)
		node = mtpmap[mtpid] = new Tree(mtpid, parent, name);
	else
		node = new Node(mtpid, parent, name);
	tree->addEntry(node);
	return node;
}

Node* MtpStorage::findNode(MtpObjectHandle handle) {
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		Node* node = i->second->findNode(handle);
		if (node != NULL) {
			MTPD("findNode: found node %p for handle %u, name: %s\n", node, handle, node->getName().c_str());
			if (node->Mtpid() != handle)
			{
				MTPE("BUG: entry for handle %u points to node with handle %u\n", handle, node->Mtpid());
			}
			return node;
		}
	}
	// Item is not on this storage device
	MTPD("MtpStorage::findNode: no node found for handle %u on storage %u, searched %u trees\n", handle, mStorageID, mtpmap.size());
	return NULL;
}

std::string MtpStorage::getNodePath(Node* node) {
	std::string path;
	MTPD("getNodePath: node %p, handle %u\n", node, node->Mtpid());
	while (node)
	{
		path = "/" + node->getName() + path;
		MtpObjectHandle parent = node->getMtpParentId();
		if (parent == 0)	// root
			break;
		node = findNode(parent);
	}
	path = mtpstorageparent + path;
	MTPD("getNodePath: path %s\n", path.c_str());
	return path;
}

void MtpStorage::lockMutex(int thread_type) {
	if (!use_mutex)
		return; // mutex is disabled
	if (thread_type) {
		// inotify thread
		pthread_mutex_lock(&inMutex);
		while (pthread_mutex_trylock(&mtpMutex)) {
			pthread_mutex_unlock(&inMutex);
			usleep(32000);
			pthread_mutex_lock(&inMutex);
		}
	} else {
		// main mtp thread
		pthread_mutex_lock(&mtpMutex);
		while (pthread_mutex_trylock(&inMutex)) {
			pthread_mutex_unlock(&mtpMutex);
			usleep(13000);
			pthread_mutex_lock(&mtpMutex);
		}
	}
}

void MtpStorage::unlockMutex(int thread_type) {
	if (!use_mutex)
		return; // mutex is disabled
	pthread_mutex_unlock(&inMutex);
	pthread_mutex_unlock(&mtpMutex);
}
