Merge "Remove unused fonts from 320x480" into twrp2.4
diff --git a/exfat/exfat-fuse/main.c b/exfat/exfat-fuse/main.c
index 7f4ac18..0023b9d 100644
--- a/exfat/exfat-fuse/main.c
+++ b/exfat/exfat-fuse/main.c
@@ -38,7 +38,8 @@
 	#error FUSE 2.6 or later is required
 #endif
 
-const char* default_options = "ro_fallback,allow_other,blkdev,big_writes";
+const char* default_options = "ro_fallback,allow_other,blkdev,big_writes,"
+		"defer_permissions";
 
 struct exfat ef;
 
@@ -79,7 +80,7 @@
 	if (rc != 0)
 		return rc;
 
-	rc = exfat_truncate(&ef, node, size);
+	rc = exfat_truncate(&ef, node, size, true);
 	exfat_put_node(&ef, node);
 	return rc;
 }
@@ -343,19 +344,6 @@
 	return options;
 }
 
-static char* add_fsname_option(char* options, const char* spec)
-{
-	char spec_abs[PATH_MAX];
-
-	if (realpath(spec, spec_abs) == NULL)
-	{
-		free(options);
-		exfat_error("failed to get absolute path for `%s'", spec);
-		return NULL;
-	}
-	return add_option(options, "fsname", spec_abs);
-}
-
 static char* add_user_option(char* options)
 {
 	struct passwd* pw;
@@ -387,7 +375,7 @@
 
 static char* add_fuse_options(char* options, const char* spec)
 {
-	options = add_fsname_option(options, spec);
+	options = add_option(options, "fsname", spec);
 	if (options == NULL)
 		return NULL;
 	options = add_user_option(options);
diff --git a/exfat/libexfat/cluster.c b/exfat/libexfat/cluster.c
index 83c983d..d10a5df 100644
--- a/exfat/libexfat/cluster.c
+++ b/exfat/libexfat/cluster.c
@@ -106,41 +106,24 @@
 	return node->fptr_cluster;
 }
 
-static cluster_t find_bit_and_set(uint8_t* bitmap, cluster_t start,
-		cluster_t end)
+static cluster_t find_bit_and_set(uint8_t* bitmap, size_t start, size_t end)
 {
-	const cluster_t mid_start = (start + 7) / 8 * 8;
-	const cluster_t mid_end = end / 8 * 8;
-	cluster_t c;
-	cluster_t byte;
+	const size_t start_index = start / 8;
+	const size_t end_index = DIV_ROUND_UP(end, 8);
+	size_t i;
+	size_t c;
 
-	for (c = start; c < mid_start; c++)
-		if (BMAP_GET(bitmap, c) == 0)
-		{
-			BMAP_SET(bitmap, c);
-			return c + EXFAT_FIRST_DATA_CLUSTER;
-		}
-
-	for (byte = mid_start / 8; byte < mid_end / 8; byte++)
-		if (bitmap[byte] != 0xff)
-		{
-			cluster_t bit;
-
-			for (bit = 0; bit < 8; bit++)
-				if (!(bitmap[byte] & (1u << bit)))
-				{
-					bitmap[byte] |= (1u << bit);
-					return byte * 8 + bit + EXFAT_FIRST_DATA_CLUSTER;
-				}
-		}
-
-	for (c = mid_end; c < end; c++)
-		if (BMAP_GET(bitmap, c) == 0)
-		{
-			BMAP_SET(bitmap, c);
-			return c + EXFAT_FIRST_DATA_CLUSTER;
-		}
-
+	for (i = start_index; i < end_index; i++)
+	{
+		if (bitmap[i] == 0xff)
+			continue;
+		for (c = MAX(i * 8, start); c < MIN((i + 1) * 8, end); c++)
+			if (BMAP_GET(bitmap, c) == 0)
+			{
+				BMAP_SET(bitmap, c);
+				return c + EXFAT_FIRST_DATA_CLUSTER;
+			}
+	}
 	return EXFAT_CLUSTER_END;
 }
 
@@ -151,7 +134,7 @@
 	ef->cmap.dirty = false;
 }
 
-static void set_next_cluster(const struct exfat* ef, int contiguous,
+static void set_next_cluster(const struct exfat* ef, bool contiguous,
 		cluster_t current, cluster_t next)
 {
 	off64_t fat_offset;
@@ -204,7 +187,7 @@
 	cluster_t c;
 
 	for (c = first; c < last; c++)
-		set_next_cluster(ef, 0, c, c + 1);
+		set_next_cluster(ef, false, c, c + 1);
 }
 
 static int shrink_file(struct exfat* ef, struct exfat_node* node,
@@ -361,7 +344,8 @@
 	return 0;
 }
 
-int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size)
+int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
+		bool erase)
 {
 	uint32_t c1 = bytes2clusters(ef, node->size);
 	uint32_t c2 = bytes2clusters(ef, size);
@@ -381,9 +365,12 @@
 	if (rc != 0)
 		return rc;
 
-	rc = erase_range(ef, node, node->size, size);
-	if (rc != 0)
-		return rc;
+	if (erase)
+	{
+		rc = erase_range(ef, node, node->size, size);
+		if (rc != 0)
+			return rc;
+	}
 
 	exfat_update_mtime(node);
 	node->size = size;
diff --git a/exfat/libexfat/exfat.h b/exfat/libexfat/exfat.h
index 11be06f..3e4223e 100644
--- a/exfat/libexfat/exfat.h
+++ b/exfat/libexfat/exfat.h
@@ -164,7 +164,8 @@
 cluster_t exfat_advance_cluster(const struct exfat* ef,
 		struct exfat_node* node, uint32_t count);
 void exfat_flush_cmap(struct exfat* ef);
-int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size);
+int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
+		bool erase);
 uint32_t exfat_count_free_clusters(const struct exfat* ef);
 int exfat_find_used_sectors(const struct exfat* ef, off64_t* a, off64_t* b);
 
diff --git a/exfat/libexfat/io.c b/exfat/libexfat/io.c
index 1be028c..7f79d97 100644
--- a/exfat/libexfat/io.c
+++ b/exfat/libexfat/io.c
@@ -2,7 +2,7 @@
 	io.c (02.09.09)
 	exFAT file system implementation library.
 
-	Copyright (C) 2010-2012  Andrew Nayenko
+	Copyright (C) 2010-2013  Andrew Nayenko
 
 	This program is free software: you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -350,10 +350,13 @@
 	cluster_t cluster;
 	const char* bufp = buffer;
 	off64_t lsize, loffset, remainder;
-	printf("node: %s\n", node);
-	if (offset + size > node->size)
-		if (exfat_truncate(ef, node, offset + size) != 0)
-			return -1;
+
+ 	if (offset > node->size)
+ 		if (exfat_truncate(ef, node, offset, true) != 0)
+ 			return -1;
+  	if (offset + size > node->size)
+ 		if (exfat_truncate(ef, node, offset + size, false) != 0)
+ 			return -1;
 	if (size == 0)
 		return 0;
 
diff --git a/exfat/libexfat/node.c b/exfat/libexfat/node.c
index ff2cea9..c2ee0da 100644
--- a/exfat/libexfat/node.c
+++ b/exfat/libexfat/node.c
@@ -56,7 +56,7 @@
 		if (node->flags & EXFAT_ATTRIB_UNLINKED)
 		{
 			/* free all clusters and node structure itself */
-			exfat_truncate(ef, node, 0);
+			exfat_truncate(ef, node, 0, true);
 			free(node);
 		}
 		if (ef->cmap.dirty)
@@ -457,17 +457,40 @@
 	return 0;
 }
 
+static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
+{
+	node->parent = dir;
+	if (dir->child)
+	{
+		dir->child->prev = node;
+		node->next = dir->child;
+	}
+	dir->child = node;
+}
+
+static void tree_detach(struct exfat_node* node)
+{
+	if (node->prev)
+		node->prev->next = node->next;
+	else /* this is the first node in the list */
+		node->parent->child = node->next;
+	if (node->next)
+		node->next->prev = node->prev;
+	node->parent = NULL;
+	node->prev = NULL;
+	node->next = NULL;
+}
+
 static void reset_cache(struct exfat* ef, struct exfat_node* node)
 {
-	struct exfat_node* child;
-	struct exfat_node* next;
-
-	for (child = node->child; child; child = next)
+	while (node->child)
 	{
-		reset_cache(ef, child);
-		next = child->next;
-		free(child);
+		struct exfat_node* p = node->child;
+		reset_cache(ef, p);
+		tree_detach(p);
+		free(p);
 	}
+	node->flags &= ~EXFAT_ATTRIB_CACHED;
 	if (node->references != 0)
 	{
 		char buffer[EXFAT_NAME_MAX + 1];
@@ -475,10 +498,8 @@
 		exfat_warn("non-zero reference counter (%d) for `%s'",
 				node->references, buffer);
 	}
-	while (node->references--)
+	while (node->references)
 		exfat_put_node(ef, node);
-	node->child = NULL;
-	node->flags &= ~EXFAT_ATTRIB_CACHED;
 }
 
 void exfat_reset_cache(struct exfat* ef)
@@ -563,30 +584,6 @@
 	}
 }
 
-static void tree_detach(struct exfat_node* node)
-{
-	if (node->prev)
-		node->prev->next = node->next;
-	else /* this is the first node in the list */
-		node->parent->child = node->next;
-	if (node->next)
-		node->next->prev = node->prev;
-	node->parent = NULL;
-	node->prev = NULL;
-	node->next = NULL;
-}
-
-static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
-{
-	node->parent = dir;
-	if (dir->child)
-	{
-		dir->child->prev = node;
-		node->next = dir->child;
-	}
-	dir->child = node;
-}
-
 static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
 		off64_t deleted_offset)
 {
@@ -630,7 +627,7 @@
 		new_size = CLUSTER_SIZE(*ef->sb);
 	if (new_size == dir->size)
 		return 0;
-	rc = exfat_truncate(ef, dir, new_size);
+	rc = exfat_truncate(ef, dir, new_size, true);
 	if (rc != 0)
 		return rc;
 	return 0;
@@ -676,7 +673,7 @@
 {
 	return exfat_truncate(ef, dir,
 			DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
-				* CLUSTER_SIZE(*ef->sb));
+				* CLUSTER_SIZE(*ef->sb), true);
 }
 
 static int find_slot(struct exfat* ef, struct exfat_node* dir,
@@ -829,7 +826,7 @@
 	if (rc != 0)
 		return 0;
 	/* directories always have at least one cluster */
-	rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
+	rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb), true);
 	if (rc != 0)
 	{
 		delete(ef, node);