/*
 * 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>
#include "tw_sys_atomics.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;
	inotify_fd = -1;
	// Threading has not started yet so we should be safe to set these directly instead of using atomics
	inotify_thread_kill = 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");
		pthread_mutex_destroy(&mtpMutex);
		use_mutex = false;
	}
}

MtpStorage::~MtpStorage() {
	if (inotify_thread) {
		__tw_atomic_cmpxchg(0, 1, &inotify_thread_kill);
		//inotify_thread_kill = 1;
		MTPD("joining inotify_thread after sending the kill notification.\n");
		pthread_join(inotify_thread, NULL); // There's not much we can do if there's an error here
		inotify_thread = 0;
		MTPD("~MtpStorage removing inotify watches and closing inotify_fd\n");
		for (std::map<int, Tree*>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
			inotify_rm_watch(inotify_fd, i->first);
		}
		close(inotify_fd);
		inotifymap.clear();
	}
	// Deleting the root tree causes a cascade in btree.cpp that ends up
	// deleting all of the trees and nodes.
	delete mtpmap[0];
	mtpmap.clear();
	if (use_mutex) {
		use_mutex = false;
		MTPD("~MtpStorage destroying mutexes\n");
		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) {
		sendEvents = true;
		MTPD("inotify_init\n");
		inotify_fd = inotify_init();
		if (inotify_fd < 0) {
			MTPE("Can't run inotify_init for mtp server: %s\n", strerror(errno));
		} else {
			MTPD("Starting inotify thread\n");
			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;
	pthread_attr_t tattr;

	if (pthread_attr_init(&tattr)) {
		MTPE("Unable to pthread_attr_init\n");
		return 0;
	}
	if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
		MTPE("Error setting pthread_attr_setdetachstate\n");
		return 0;
	}
	ThreadPtr inotifyptr = &MtpStorage::inotify_t;
	PThreadPtr p = *(PThreadPtr*)&inotifyptr;
	pthread_create(&thread, &tattr, p, this);
	if (pthread_attr_destroy(&tattr)) {
		MTPE("Failed to pthread_attr_destroy\n");
	}
	return thread;
}

int MtpStorage::addInotify(Tree* tree) {
	if (inotify_fd < 0) {
		MTPE("inotify_fd not set or error: %i\n", inotify_fd);
		return -1;
	}
	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];
	fd_set fdset;
	struct timeval seltmout;
	int sel_ret;

	MTPD("inotify thread starting.\n");

	while (__tw_atomic_cmpxchg(0, inotify_thread_kill, &inotify_thread_kill) == 0) {
		FD_ZERO(&fdset);
		FD_SET(inotify_fd, &fdset);
		seltmout.tv_sec = 0;
		seltmout.tv_usec = 25000;
		sel_ret = select(inotify_fd + 1, &fdset, NULL, NULL, &seltmout);
		if (sel_ret == 0)
			continue;
		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 && __tw_atomic_cmpxchg(0, inotify_thread_kill, &inotify_thread_kill) == 0) {
			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;
		}
	}
	MTPD("inotify_thread_kill received!\n");
	// This cleanup is handled in the destructor.
	/*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);
}
