changeset 211:fad21fd1971d

Check in inband tags, some extra yaffs direct functions and some other changes
author charles
date Mon, 05 May 2008 08:58:58 +0100
parents 15cda41fdfb6
children 810921c6d869
files devextras.h direct/Makefile direct/dtest.c direct/fsx_test/Makefile direct/fsx_test/yaffs_fsx.c direct/yaffs_fileem2k.c direct/yaffs_flashif.h direct/yaffs_ramdisk.c direct/yaffs_ramdisk.h direct/yaffs_ramem2k.c direct/yaffscfg2k.c direct/yaffsfs.c direct/yaffsfs.h direct/ydirectenv.h yaffs_checkptrw.c yaffs_fs.c yaffs_guts.c yaffs_guts.h yaffs_mtdif2.c yaffs_nand.c yaffs_nandemul2k.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_tagscompat.c yaffs_tagscompat.h yportenv.h
diffstat 26 files changed, 1373 insertions(+), 683 deletions(-) [+]
line wrap: on
line diff
--- a/devextras.h
+++ b/devextras.h
@@ -23,31 +23,29 @@
 #ifndef __EXTRAS_H__
 #define __EXTRAS_H__
 
-#if defined WIN32
-#define __inline__ __inline
-#define new newHack
-#endif
 
-#if !(defined __KERNEL__) || (defined WIN32)
+#if !(defined __KERNEL__)
 
 /* Definition of types */
 typedef unsigned char __u8;
 typedef unsigned short __u16;
 typedef unsigned __u32;
 
+#endif
+
 /*
  * This is a simple doubly linked list implementation that matches the 
  * way the Linux kernel doubly linked list implementation works.
  */
 
-struct list_head {
-	struct list_head *next; /* next in chain */
-	struct list_head *prev; /* previous in chain */
+struct ylist_head {
+	struct ylist_head *next; /* next in chain */
+	struct ylist_head *prev; /* previous in chain */
 };
 
 
 /* Initialise a list head to an empty list */
-#define INIT_LIST_HEAD(p) \
+#define YINIT_LIST_HEAD(p) \
 do { \
  (p)->next = (p);\
  (p)->prev = (p); \
@@ -55,10 +53,10 @@ do { \
 
 
 /* Add an element to a list */
-static __inline__ void list_add(struct list_head *newEntry, 
-				struct list_head *list)
+static __inline__ void ylist_add(struct ylist_head *newEntry, 
+				 struct ylist_head *list)
 {
-	struct list_head *listNext = list->next;
+	struct ylist_head *listNext = list->next;
 	
 	list->next = newEntry;
 	newEntry->prev = list;
@@ -70,52 +68,63 @@ static __inline__ void list_add(struct l
 
 /* Take an element out of its current list, with or without
  * reinitialising the links.of the entry*/
-static __inline__ void list_del(struct list_head *entry)
+static __inline__ void ylist_del(struct ylist_head *entry)
 {
-	struct list_head *listNext = entry->next;
-	struct list_head *listPrev = entry->prev;
+	struct ylist_head *listNext = entry->next;
+	struct ylist_head *listPrev = entry->prev;
 	
 	listNext->prev = listPrev;
 	listPrev->next = listNext;
 	
 }
 
-static __inline__ void list_del_init(struct list_head *entry)
+static __inline__ void ylist_del_init(struct ylist_head *entry)
 {
-	list_del(entry);
+	ylist_del(entry);
 	entry->next = entry->prev = entry;
 }
 
 
 /* Test if the list is empty */
-static __inline__ int list_empty(struct list_head *entry)
+static __inline__ int ylist_empty(struct ylist_head *entry)
 {
 	return (entry->next == entry);
 }
 
 
-/* list_entry takes a pointer to a list entry and offsets it to that
+/* ylist_entry takes a pointer to a list entry and offsets it to that
  * we can find a pointer to the object it is embedded in.
  */
  
  
-#define list_entry(entry, type, member) \
+#define ylist_entry(entry, type, member) \
 	((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
 
 
-/* list_for_each and list_for_each_safe  iterate over lists.
- * list_for_each_safe uses temporary storage to make the list delete safe
+/* ylist_for_each and list_for_each_safe  iterate over lists.
+ * ylist_for_each_safe uses temporary storage to make the list delete safe
  */
 
-#define list_for_each(itervar, list) \
+#define ylist_for_each(itervar, list) \
 	for (itervar = (list)->next; itervar != (list); itervar = itervar->next )
 
-#define list_for_each_safe(itervar,saveVar, list) \
+#define ylist_for_each_safe(itervar,saveVar, list) \
 	for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
 	 itervar = saveVar, saveVar = saveVar->next)
 
+
+#if !(defined __KERNEL__)
+
+
+#ifndef WIN32
+#include <sys/stat.h>
+#endif
+
+
+#ifdef CONFIG_YAFFS_PROVIDE_DEFS
 /* File types */
 
+
 #define DT_UNKNOWN	0
 #define DT_FIFO		1
 #define DT_CHR		2
@@ -124,7 +133,7 @@ static __inline__ int list_empty(struct 
 #define DT_REG		8
 #define DT_LNK		10
 #define DT_SOCK		12
-#define DR_WHT		14
+#define DT_WHT		14
 
 
 #ifndef WIN32
@@ -155,21 +164,18 @@ struct iattr {
 	unsigned int ia_attr_flags;
 };
 
+#endif
+
+
 #define KERN_DEBUG
 
 #else
 
-#ifndef WIN32
 #include <linux/types.h>
-#include <linux/list.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
-#endif
 
 #endif
 
-#if defined WIN32
-#undef new
-#endif
 
 #endif
--- a/direct/Makefile
+++ b/direct/Makefile
@@ -18,8 +18,10 @@
 
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
-CFLAGS =    -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE
-CFLAGS+=    -fstack-check -O0
+CFLAGS =      -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2  
+CFLAGS +=     -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
+CFLAGS +=    -Wall -g $(EXTRA_COMPILE_FLAGS)
+#CFLAGS+=    -fstack-check -O0
 
 #CFLAGS+=   -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
 #CFLAGS+=   -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
@@ -40,7 +42,7 @@ ALLOBJS = $(DIRECTTESTOBJS) $(BOOTTESTOB
 
 SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h  yaffs_nandemul2k.h \
-          yaffs_nand.c yaffs_nand.h \
+          yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_qsort.c yaffs_qsort.h
 
@@ -49,7 +51,7 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs
 all: directtest2k
 
 $(ALLOBJS): %.o: %.c
-	gcc -c $(CFLAGS) $< -o $@
+	gcc -c $(CFLAGS) -o $@ $<
 
 $(SYMLINKS):
 	ln -s ../$@ $@
--- a/direct/dtest.c
+++ b/direct/dtest.c
@@ -1,7 +1,7 @@
 /*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ * YAFFS: Yet another FFS. A NAND-flash specific file system. 
  *
- * Copyright (C) 2002-2007 Aleph One Ltd.
+ * Copyright (C) 2002 Aleph One Ltd.
  *   for Toby Churchill Ltd and Brightstar Engineering
  *
  * Created by Charles Manning <charles@aleph1.co.uk>
@@ -9,11 +9,10 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
  */
 
-/*
-* Test code for the "direct" interface. 
-*/
+
 
 
 #include <stdio.h>
@@ -125,9 +124,7 @@ int check_pattern_file(char *fn)
 int dump_file_data(char *fn)
 {
 	int h;
-	int marker;
 	int i = 0;
-	int size;
 	int ok = 1;
 	unsigned char b;
 	
@@ -178,6 +175,7 @@ void create_file_of_size(const char *fn,
 {
 	int h;
 	int n;
+	int result;
 	
 	char xx[200];
 	
@@ -188,7 +186,10 @@ void create_file_of_size(const char *fn,
 	while (iterations > 0)
 	{
 		sprintf(xx,"%s %8d",fn,iterations);
-		yaffs_write(h,xx,strlen(xx));
+		n = strlen(xx);
+		result = yaffs_write(h,xx,n);
+		if(result != n)
+			printf("Wrote %d, should have been %d\n",result,n);
 		iterations--;
 	}
 	yaffs_close (h);
@@ -197,7 +198,7 @@ void create_file_of_size(const char *fn,
 void verify_file_of_size(const char *fn,int syze)
 {
 	int h;
-	int n;
+	int result;
 	
 	char xx[200];
 	char yy[200];
@@ -212,11 +213,11 @@ void verify_file_of_size(const char *fn,
 		sprintf(xx,"%s %8d",fn,iterations);
 		l = strlen(xx);
 		
-		yaffs_read(h,yy,l);
+		result = yaffs_read(h,yy,l);
 		yy[l] = 0;
 		
 		if(strcmp(xx,yy)){
-			printf("=====>>>>> verification of file %s failed near position %d\n",fn,yaffs_lseek(h,0,SEEK_CUR));
+			printf("=====>>>>> verification of file %s failed near position %lld\n",fn,(long long)yaffs_lseek(h,0,SEEK_CUR));
 		}
 		iterations--;
 	}
@@ -226,8 +227,6 @@ void verify_file_of_size(const char *fn,
 void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2)
 {
 	int h;
-	int n;
-	
 	
 	int iterations;
 	
@@ -240,7 +239,7 @@ void create_resized_file_of_size(const c
 		iterations--;
 	}
 	
-	yaffs_truncate(h,reSyze);
+	yaffs_ftruncate(h,reSyze);
 	
 	yaffs_lseek(h,0,SEEK_SET);
 	iterations = (syze2 + strlen(fn) -1)/ strlen(fn);
@@ -375,7 +374,7 @@ void scan_pattern_test(const char *path,
 	}
 }
 
-void fill_disk(char *path,int nfiles)
+void fill_disk(const char *path,int nfiles)
 {
 	int h;
 	int n;
@@ -401,7 +400,7 @@ void fill_disk(char *path,int nfiles)
 	}
 }
 
-void fill_disk_and_delete(char *path, int nfiles, int ncycles)
+void fill_disk_and_delete(const char *path, int nfiles, int ncycles)
 {
 	int i,j;
 	char str[50];
@@ -883,18 +882,12 @@ int huge_directory_test_on_path(char *pa
 
 	int f;
 	int i;
-	int r;
+
 	int total = 0;
 	int lastTotal = 0;
-	char buffer[20];
 	
 	char str[100];
-	char name[100];
-	char name2[100];
-	
-	int h;
-	mode_t temp_mode;
-	struct yaffs_stat ystat;
+
 	
 	yaffs_StartUp();
 	
@@ -939,6 +932,7 @@ int huge_directory_test_on_path(char *pa
 
 int yaffs_scan_test(const char *path)
 {
+	return 0;
 }
 
 
@@ -1012,7 +1006,7 @@ int resize_stress_test(const char *path)
 				
 				syz -= 500;
 				if(syz < 0) syz = 0;
-				yaffs_truncate(a,syz);
+				yaffs_ftruncate(a,syz);
 				
 			}
 			else
@@ -1041,6 +1035,7 @@ int resize_stress_test_no_grow_complex(c
    
    char abuffer[1000];
    char bbuffer[1000];
+
    
    yaffs_StartUp();
    
@@ -1079,7 +1074,7 @@ int resize_stress_test_no_grow_complex(c
 				
 					syz -= 2050;
 					if(syz < 0) syz = 0;
-					yaffs_truncate(a,syz);
+					yaffs_ftruncate(a,syz);
 					syz = yaffs_lseek(a,0,SEEK_END);
 					printf("shrink to %d\n",syz);
 				}
@@ -1096,7 +1091,8 @@ int resize_stress_test_no_grow_complex(c
 			
 					
 		}
-		printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END));
+		
+		printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END));
 
    }
    
@@ -1152,7 +1148,7 @@ int resize_stress_test_no_grow(const cha
 				
 					syz -= 2050;
 					if(syz < 0) syz = 0;
-					yaffs_truncate(a,syz);
+					yaffs_ftruncate(a,syz);
 					syz = yaffs_lseek(a,0,SEEK_END);
 					printf("shrink to %d\n",syz);
 				}
@@ -1169,7 +1165,7 @@ int resize_stress_test_no_grow(const cha
 			
 					
 		}
-		printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END));
+		printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END));
 
    }
    
@@ -1253,7 +1249,6 @@ int cache_bypass_bug_test(void)
 	// This bug has been fixed.
 	
 	int a;
-	int i;
 	char buffer1[1000];
 	char buffer2[1000];
 	
@@ -1327,7 +1322,7 @@ int truncate_test(void)
 	
 	yaffs_write(a,"abcdefghijklmnopqrstuvwzyz",26);
 	
-	yaffs_truncate(a,3);
+	yaffs_ftruncate(a,3);
 	l= yaffs_lseek(a,0,SEEK_END);
 	
 	printf("truncated length is %d\n",l);
@@ -1374,13 +1369,10 @@ void lookup_test(const char *mountpt)
 	int i;
 	int h;
 	char a[100];
-	char b[100];
 	
 
 	yaffs_DIR *d;
 	yaffs_dirent *de;
-	struct yaffs_stat s;
-	char str[100];
 
 	yaffs_StartUp();
 	
@@ -1441,11 +1433,7 @@ void link_test(const char *mountpt)
 	char a[100];
 	char b[100];
 	char c[100];
-	
-	int  f0;
-	int f1;
-	int f2;
-	int f3;
+
 	sprintf(a,"%s/aaa",mountpt);
 	sprintf(b,"%s/bbb",mountpt);
 	sprintf(c,"%s/ccc",mountpt);
@@ -1482,7 +1470,6 @@ void freespace_test(const char *mountpt)
 	int i;
 	int h;
 	char a[100];
-	char b[100];
 	
 	int  f0;
 	int f1;
@@ -1741,8 +1728,6 @@ void multi_mount_test(const char *mountp
 {
 
 	char a[30];
-	char b[30];
-	char c[30];
 	
 	int i;
 	int j;
@@ -1773,12 +1758,18 @@ void multi_mount_test(const char *mountp
 		
 		sprintf(xx,"%s/1",a);
 		h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
-		
+
+#if 0		
 		for(j = 0; j < 200; j++){
 		   yaffs_write(h0,xx,1000);
 		   yaffs_write(h1,xx,1000);
 		}
-		
+#else
+		while(yaffs_write(h0,xx,1000) > 0){
+		   
+		   yaffs_write(h1,xx,1000);
+		}
+#endif
 		len0 = yaffs_lseek(h0,0,SEEK_END);
 		len1 = yaffs_lseek(h1,0,SEEK_END);
 		
@@ -1791,7 +1782,7 @@ void multi_mount_test(const char *mountp
 		}
 		
 		
-		yaffs_truncate(h0,0);
+	//	yaffs_truncate(h0,0);
 		yaffs_close(h0);
 		yaffs_close(h1);
 		
@@ -1808,8 +1799,6 @@ void small_mount_test(const char *mountp
 {
 
 	char a[30];
-	char b[30];
-	char c[30];
 	
 	int i;
 	int j;
@@ -1885,17 +1874,12 @@ void small_overwrite_test(const char *mo
 {
 
 	char a[30];
-	char b[30];
-	char c[30];
-	
 	int i;
 	int j;
 
 	int h0;
 	int h1;
-	int len0;
-	int len1;
-	int nread;
+
 	
 	sprintf(a,"%s/a",mountpt);
 
@@ -1921,7 +1905,7 @@ void small_overwrite_test(const char *mo
 		h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
 		
 		for(j = 0; j < 1000000; j+=1000){
-			yaffs_truncate(h0,j);
+			yaffs_ftruncate(h0,j);
 			yaffs_lseek(h0,j,SEEK_SET);
 			yaffs_write(h0,xx,7000);
 			yaffs_write(h1,xx,7000);
@@ -1941,6 +1925,44 @@ void small_overwrite_test(const char *mo
 }
 
 
+void seek_overwrite_test(const char *mountpt,int nmounts)
+{
+
+	char a[30];
+	
+	int i;
+	int j;
+
+	int h0;
+
+	
+	sprintf(a,"%s/f",mountpt);
+
+	yaffs_StartUp();
+	
+	yaffs_mount(mountpt);
+	
+	
+	for(i = 0; i < nmounts; i++){
+		
+		h0 = yaffs_open(a, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+			
+		for(j = 0; j < 100000; j++){
+			yaffs_lseek(h0,0,SEEK_SET);
+			yaffs_write(h0,xx,5000);
+			yaffs_lseek(h0,0x100000,SEEK_SET);
+			yaffs_write(h0,xx,5000);
+			
+			if(early_exit)
+				exit(0);
+		}
+		
+		yaffs_close(h0);
+		
+	}
+}
+
+
 void yaffs_touch(const char *fn)
 {
 	yaffs_chmod(fn, S_IREAD | S_IWRITE);
@@ -2014,7 +2036,7 @@ int make_file2(const char *name1, const 
 	}
 	yaffs_close(h1);
 	yaffs_close(h2);
-	
+	return 0;
 }
 
 
@@ -2027,10 +2049,8 @@ void checkpoint_upgrade_test(const char 
 	char b[50];
 	char c[50];
 	char d[50];
-	
-	int i;
+
 	int j;
-	int h;
 	
 	sprintf(a,"%s/a",mountpt);
 	
@@ -2087,8 +2107,7 @@ void huge_array_test(const char *mountpt
 
 	
 	int i;
-	int j;
-	int h;
+	int space;
 	
 	int fnum;
 	
@@ -2104,10 +2123,10 @@ void huge_array_test(const char *mountpt
 		n--;
 		fnum = 0;
 		printf("\n\n START run\n\n");
-		while(yaffs_freespace(mountpt) > 25000000){
+		while((space = yaffs_freespace(mountpt)) > 25000000){
 			sprintf(a,"%s/file%d",mountpt,fnum);
 			fnum++;
-			printf("create file %s\n",a);
+			printf("create file %s, free space %d\n",a,space);
 			create_file_of_size(a,10000000);
 			printf("verifying file %s\n",a);
 			verify_file_of_size(a,10000000);
@@ -2153,7 +2172,7 @@ void random_truncate(int h, char * name)
 	flen = yaffs_lseek(h,0,SEEK_END);
 	if(n > flen)
 		n = flen / 2;
-	yaffs_truncate(name,n);
+	yaffs_ftruncate(h,n);
 	yaffs_lseek(h,n,SEEK_SET);
 }
 
@@ -2167,10 +2186,8 @@ void random_small_file_test(const char *
 	
 	int i;
 	int n;
-	int j;
 	int h[NSMALLFILES];
 	int r;
-	int fnum;
 	
 	
 	yaffs_StartUp();
@@ -2189,7 +2206,7 @@ void random_small_file_test(const char *
 			
 			if(strlen(a[i]) == 0){
 				sprintf(a[i],"%s/%dx%d",mountpt,n,i);
-				h[i] = yaffs_open(a,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+				h[i] = yaffs_open(a[i],O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
 			}
 			
 			if(h[i] < -1)
@@ -2249,6 +2266,10 @@ int main(int argc, char *argv[])
 	//short_scan_test("/flash/flash",40000,200);
 	  //small_mount_test("/flash/flash",1000);
 	  //small_overwrite_test("/flash/flash",1000);
+	  //seek_overwrite_test("/flash/flash",1000);
+	 //checkpoint_fill_test("/flash/flash",20);
+	 //checkpoint_upgrade_test("/flash/flash",20);
+	  //small_overwrite_test("/flash/flash",1000);
 	  //checkpoint_fill_test("/flash/flash",20);
 	// random_small_file_test("/flash/flash",10000);
 	 // huge_array_test("/flash/flash",10);
--- a/direct/fsx_test/Makefile
+++ b/direct/fsx_test/Makefile
@@ -18,7 +18,9 @@
 
 #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
-CFLAGS =    -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE
+CFLAGS =    -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -DNO_Y_INLINE
+CFLAGS+=    -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
+CFLAGS+=    -Wall -g $(EXTRA_COMPILE_FLAGS)
 CFLAGS+=    -fstack-check -O0
 
 #CFLAGS+=   -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
@@ -42,7 +44,7 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c 
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h  yaffs_nandemul2k.h \
           yaffs_nand.c yaffs_nand.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
-          yaffs_qsort.c yaffs_qsort.h
+          yaffs_qsort.c yaffs_qsort.h yaffs_getblockinfo.h
 
 YAFFSDIRECTSYMLINKS =  yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h \
 		       yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
--- a/direct/fsx_test/yaffs_fsx.c
+++ b/direct/fsx_test/yaffs_fsx.c
@@ -67,6 +67,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <errno.h>
+#include <time.h>
 
 #include "yaffsfs.h"
 
@@ -421,14 +422,14 @@ check_trunc_hack(void)
 {
 	struct yaffs_stat statbuf;
 
-	yaffs_truncate(fd, (off_t)0);
-	yaffs_truncate(fd, (off_t)100000);
+	yaffs_ftruncate(fd, (off_t)0);
+	yaffs_ftruncate(fd, (off_t)100000);
 	yaffs_fstat(fd, &statbuf);
 	if (statbuf.st_size != (off_t)100000) {
 		prt("no extend on truncate! not posix!\n");
 		exit(130);
 	}
-	yaffs_truncate(fd, (off_t)0);
+	yaffs_ftruncate(fd, (off_t)0);
 }
 
 
@@ -579,7 +580,7 @@ dotruncate(unsigned size)
 	    (debug && (monitorstart == -1 || monitorend == -1 ||
 		       size <= monitorend)))
 		prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize, size);
-	if (yaffs_truncate(fd, (off_t)size) == -1) {
+	if (yaffs_ftruncate(fd, (off_t)size) == -1) {
 		prt("ftruncate1: %x\n", size);
 		prterr("dotruncate: ftruncate");
 		report_failure(160);
@@ -605,7 +606,7 @@ writefileimage()
 			    iret, (unsigned long long)file_size);
 		report_failure(172);
 	}
-	if (lite ? 0 : yaffs_truncate(fd, file_size) == -1) {
+	if (lite ? 0 : yaffs_ftruncate(fd, file_size) == -1) {
 		prt("ftruncate2: %llx\n", (unsigned long long)file_size);
 		prterr("writefileimage: ftruncate");
 		report_failure(173);
--- a/direct/yaffs_fileem2k.c
+++ b/direct/yaffs_fileem2k.c
@@ -103,16 +103,10 @@ static int GetBlockFileHandle(int n)
 static int  CheckInit(void)
 {
 	static int initialised = 0;
-	int h;
 	int i;
 
-	
-	off_t fSize;
-	off_t requiredSize;
-	int written;
 	int blk;
-	
-	yflash_Page p;
+
 	
 	if(initialised) 
 	{
@@ -144,7 +138,7 @@ int yflash_GetNumberOfBlocks(void)
 	return filedisk.nBlocks;
 }
 
-int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
 {
 	int written;
 	int pos;
@@ -158,90 +152,114 @@ int yflash_WriteChunkWithTagsToNAND(yaff
 	CheckInit();
 	
 	
-	
-	if(data)
-	{
+	if(dev->inbandTags){
+		
+		yaffs_PackedTags2TagsPart * pt2tp;
+		pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+		yaffs_PackTags2TagsPart(pt2tp,tags);
+		
 		pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
 		h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-		
+				  			
 		lseek(h,pos,SEEK_SET);
-		nRead =  read(h, localBuffer,dev->nDataBytesPerChunk);
-		for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){
-			if(localBuffer[i] != 0xFF){
-				printf("nand simulation: chunk %d data byte %d was %0x2\n",
-					chunkInNAND,i,localBuffer[i]);
-				error = 1;
-			}
-		}
-		
-		for(i = 0; i < dev->nDataBytesPerChunk; i++)
-		  localBuffer[i] &= data[i];
-		  
-		if(memcmp(localBuffer,data,dev->nDataBytesPerChunk))
-			printf("nand simulator: data does not match\n");
-			
-		lseek(h,pos,SEEK_SET);
-		written = write(h,localBuffer,dev->nDataBytesPerChunk);
+		written = write(h,data,dev->totalBytesPerChunk);
+
 		
 		if(yaffs_testPartialWrite){
 			close(h);
 			exit(1);
 		}
 		
+		if(written != dev->totalBytesPerChunk) return YAFFS_FAIL;
+
+
+	}
+	
+	else {
+	
+		if(data)
+		{
+			pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+			h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+		
+			lseek(h,pos,SEEK_SET);
+			nRead =  read(h, localBuffer,dev->nDataBytesPerChunk);
+			for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){
+				if(localBuffer[i] != 0xFF){
+					printf("nand simulation: chunk %d data byte %d was %0x2\n",
+						chunkInNAND,i,localBuffer[i]);
+					error = 1;
+				}
+			}
+		
+			for(i = 0; i < dev->nDataBytesPerChunk; i++)
+			localBuffer[i] &= data[i];
+		  
+			if(memcmp(localBuffer,data,dev->nDataBytesPerChunk))
+				printf("nand simulator: data does not match\n");
+			
+			lseek(h,pos,SEEK_SET);
+			written = write(h,localBuffer,dev->nDataBytesPerChunk);
+		
+			if(yaffs_testPartialWrite){
+				close(h);
+				exit(1);
+			}
+		
 #ifdef SIMULATE_FAILURES
-			if((chunkInNAND >> 6) == 100) 
-			  written = 0;
+				if((chunkInNAND >> 6) == 100) 
+				written = 0;
 
-			if((chunkInNAND >> 6) == 110) 
-			  written = 0;
+				if((chunkInNAND >> 6) == 110) 
+				written = 0;
 #endif
 
 
-		if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
-	}
+			if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
+		}
 	
-	if(tags)
-	{
-		pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
-		h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+		if(tags)
+		{
+			pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
+			h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
 		
-		lseek(h,pos,SEEK_SET);
+			lseek(h,pos,SEEK_SET);
 
-		if( 0 && dev->isYaffs2)
-		{
+			if( 0 && dev->isYaffs2)
+			{
 			
-			written = write(h,tags,sizeof(yaffs_ExtendedTags));
-			if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
-		}
-		else
-		{
-			yaffs_PackedTags2 pt;
-			yaffs_PackTags2(&pt,tags);
-			__u8 * ptab = (__u8 *)&pt;
+				written = write(h,tags,sizeof(yaffs_ExtendedTags));
+				if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
+			}
+			else
+			{
+				yaffs_PackedTags2 pt;
+				yaffs_PackTags2(&pt,tags);
+				__u8 * ptab = (__u8 *)&pt;
 
-			nRead = read(h,localBuffer,sizeof(pt));
-			for(i = error = 0; i < sizeof(pt) && !error; i++){
-				if(localBuffer[i] != 0xFF){
-					printf("nand simulation: chunk %d oob byte %d was %0x2\n",
-						chunkInNAND,i,localBuffer[i]);
-						error = 1;
+				nRead = read(h,localBuffer,sizeof(pt));
+				for(i = error = 0; i < sizeof(pt) && !error; i++){
+					if(localBuffer[i] != 0xFF){
+						printf("nand simulation: chunk %d oob byte %d was %0x2\n",
+							chunkInNAND,i,localBuffer[i]);
+							error = 1;
+					}
 				}
-			}
 		
-			for(i = 0; i < sizeof(pt); i++)
-			  localBuffer[i] &= ptab[i];
+				for(i = 0; i < sizeof(pt); i++)
+				localBuffer[i] &= ptab[i];
 			 
-			if(memcmp(localBuffer,&pt,sizeof(pt)))
-				printf("nand sim: tags corruption\n");
+				if(memcmp(localBuffer,&pt,sizeof(pt)))
+					printf("nand sim: tags corruption\n");
 				
-			lseek(h,pos,SEEK_SET);
+				lseek(h,pos,SEEK_SET);
 			
-			written = write(h,localBuffer,sizeof(pt));
-			if(written != sizeof(pt)) return YAFFS_FAIL;
+				written = write(h,localBuffer,sizeof(pt));
+				if(written != sizeof(pt)) return YAFFS_FAIL;
+			}
 		}
+	
 	}
-	
-
 	return YAFFS_OK;	
 
 }
@@ -268,6 +286,9 @@ int yflash_ReadChunkWithTagsFromNAND(yaf
 	int nread;
 	int pos;
 	int h;
+	int localData = 0;
+	int retval = YAFFS_OK;
+	int nRead;
 	
 	T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags));
 	
@@ -275,68 +296,107 @@ int yflash_ReadChunkWithTagsFromNAND(yaf
 	
 	
 	
-	if(data)
-	{
+	
+	if(dev->inbandTags){
+		/* Got to suck the tags out of the data area */
+		if(!data) {
+			localData=1;
+			data = yaffs_GetTempBuffer(dev,__LINE__);
+		}
 
+		
+		yaffs_PackedTags2TagsPart * pt2tp;
+		pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
+
+		
 		pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
-		h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];		
+		h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+		
 		lseek(h,pos,SEEK_SET);
-		nread = read(h,data,dev->nDataBytesPerChunk);
+
+		nRead = read(h, data,dev->totalBytesPerChunk);
+
+		yaffs_UnpackTags2TagsPart(tags,pt2tp);
 		
-		
-		if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL;
+		if(nread != dev->totalBytesPerChunk)
+			retval = YAFFS_FAIL;
+			
+		if(localData)
+			yaffs_ReleaseTempBuffer(dev,data,__LINE__);
+
+
+
 	}
 	
-	if(tags)
-	{
-		pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
-		h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];		
-		lseek(h,pos,SEEK_SET);
+	else {
+	
+		if(data)
+		{
 
-		if(0 && dev->isYaffs2)
+			pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+			h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];		
+			lseek(h,pos,SEEK_SET);
+			nread = read(h,data,dev->nDataBytesPerChunk);
+		
+		
+			if(nread != dev->nDataBytesPerChunk) 
+				retval = YAFFS_FAIL;
+		}
+	
+		if(tags)
 		{
-			nread= read(h,tags,sizeof(yaffs_ExtendedTags));
-			if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
-			if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
+			pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
+			h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];		
+			lseek(h,pos,SEEK_SET);
+
+			if(0 && dev->isYaffs2)
 			{
-				yaffs_InitialiseTags(tags);
+				nread= read(h,tags,sizeof(yaffs_ExtendedTags));
+				if(nread != sizeof(yaffs_ExtendedTags))
+					 retval =  YAFFS_FAIL;
+				if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
+				{
+					yaffs_InitialiseTags(tags);
+				}
+				else
+				{
+					tags->chunkUsed = 1;
+				}
 			}
 			else
 			{
-				tags->chunkUsed = 1;
-			}
-		}
-		else
-		{
-			yaffs_PackedTags2 pt;
-			nread= read(h,&pt,sizeof(pt));
-			yaffs_UnpackTags2(tags,&pt);
+				yaffs_PackedTags2 pt;
+				nread= read(h,&pt,sizeof(pt));
+				yaffs_UnpackTags2(tags,&pt);
 #ifdef SIMULATE_FAILURES
-			if((chunkInNAND >> 6) == 100) {
-			    if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
-			       tags->eccResult = YAFFS_ECC_RESULT_FIXED;
-			       fail300 = 0;
-			    }
-			    
+				if((chunkInNAND >> 6) == 100) {
+					if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+						tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+						fail300 = 0;
+					}
+				}
+				
+				if((chunkInNAND >> 6) == 110) {
+					if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+						tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+						fail320 = 0;
+					}
+				}
+#endif
+				if(failRead10>0 && chunkInNAND == 10){
+					failRead10--;
+					nread = 0;
+				}
+			
+				if(nread != sizeof(pt))
+					retval = YAFFS_FAIL;
 			}
-			if((chunkInNAND >> 6) == 110) {
-			    if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
-			       tags->eccResult = YAFFS_ECC_RESULT_FIXED;
-			       fail320 = 0;
-			    }
-			}
-#endif
-			if(failRead10>0 && chunkInNAND == 10){
-				failRead10--;
-				nread = 0;
-			}
-			
-			if(nread != sizeof(pt)) return YAFFS_FAIL;
 		}
 	}
 	
 
-	return YAFFS_OK;	
+
+	return retval;	
 
 }
 
@@ -413,7 +473,7 @@ int yflash_InitialiseNAND(yaffs_Device *
 
 
 
-int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
+int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber)
 {
 	yaffs_ExtendedTags tags;
 	int chunkNo;
--- a/direct/yaffs_flashif.h
+++ b/direct/yaffs_flashif.h
@@ -20,12 +20,12 @@
 #include "yaffs_guts.h"
 int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
 int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
-int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
 int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
 int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
 int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
 int yflash_InitialiseNAND(yaffs_Device *dev);
 int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
-int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
+int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber);
 
 #endif
--- a/direct/yaffs_ramdisk.c
+++ b/direct/yaffs_ramdisk.c
@@ -118,7 +118,7 @@ static int  CheckInit(yaffs_Device *dev)
 	return 1;
 }
 
-int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
 {
 	int blk;
 	int pg;
--- a/direct/yaffs_ramdisk.h
+++ b/direct/yaffs_ramdisk.h
@@ -23,7 +23,7 @@
 
 #include "yaffs_guts.h"
 int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
-int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
 int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
 int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
 int yramdisk_InitialiseNAND(yaffs_Device *dev);
--- a/direct/yaffs_ramem2k.c
+++ b/direct/yaffs_ramem2k.c
@@ -190,7 +190,7 @@ static int  CheckInit(void)
 	return 1;
 }
 
-int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
+int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
 {
 	int blk;
 	int pg;
@@ -327,7 +327,7 @@ int nandemul2k_MarkNANDBlockBad(struct y
 	
 }
 
-int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
+int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32  *sequenceNumber)
 {
 	yaffs_ExtendedTags tags;
 	int chunkNo;
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -34,19 +34,22 @@ unsigned yaffs_traceMask =
 	YAFFS_TRACE_ALLOCATE | 
 	YAFFS_TRACE_CHECKPOINT |
 	YAFFS_TRACE_BAD_BLOCKS |
-	YAFFS_TRACE_VERIFY |
-	YAFFS_TRACE_VERIFY_NAND |
-	YAFFS_TRACE_VERIFY_FULL |
-//	(~0) |
 	
 	0;
         
 
+static int yaffsfs_lastError;
 
 void yaffsfs_SetError(int err)
 {
 	//Do whatever to set error
-	errno = err;
+	yaffsfs_lastError = err;
+}
+
+
+int yaffsfs_GetLastError(void)
+{
+	return yaffsfs_lastError;
 }
 
 void yaffsfs_Lock(void)
@@ -69,7 +72,7 @@ static size_t malloc_limit = 0 & 6000000
 
 void *yaffs_malloc(size_t size)
 {
-	size_t this;
+	void * this;
 	if(yaffs_kill_alloc)
 		return NULL;
 	if(malloc_limit && malloc_limit <(total_malloced + size) )
@@ -121,6 +124,7 @@ static yaffsfs_DeviceConfiguration yaffs
 	{ "/flash/boot", &bootDev},
 	{ "/flash/flash", &flashDev},
 	{ "/ram2k", &ram2kDev},
+	{ "/flash/bigblock", &flashDev},
 	{(void *)0,(void *)0} /* Null entry to terminate list */
 #endif
 };
@@ -135,7 +139,7 @@ int yaffs_StartUp(void)
 	// Set up devices
 	// /ram
 	memset(&ramDev,0,sizeof(ramDev));
-	ramDev.nDataBytesPerChunk = 512;
+	ramDev.totalBytesPerChunk = 512;
 	ramDev.nChunksPerBlock = 32;
 	ramDev.nReservedBlocks = 2; // Set this smaller for RAM
 	ramDev.startBlock = 0; // Can use block 0
@@ -150,7 +154,7 @@ int yaffs_StartUp(void)
 
 	// /boot
 	memset(&bootDev,0,sizeof(bootDev));
-	bootDev.nDataBytesPerChunk = 512;
+	bootDev.totalBytesPerChunk = 512;
 	bootDev.nChunksPerBlock = 32;
 	bootDev.nReservedBlocks = 5;
 	bootDev.startBlock = 0; // Can use block 0
@@ -173,9 +177,10 @@ int yaffs_StartUp(void)
 	// 2kpage/64chunk per block/128MB device
 	memset(&flashDev,0,sizeof(flashDev));
 
-	flashDev.nDataBytesPerChunk = 2048;
+	flashDev.totalBytesPerChunk = 512;
 	flashDev.nChunksPerBlock = 64;
 	flashDev.nReservedBlocks = 5;
+	flashDev.inbandTags = 1;
 	//flashDev.checkpointStartBlock = 1;
 	//flashDev.checkpointEndBlock = 20;
 	flashDev.startBlock = 0;
@@ -198,7 +203,7 @@ int yaffs_StartUp(void)
 	// 2kpage/64chunk per block/128MB device
 	memset(&ram2kDev,0,sizeof(ram2kDev));
 
-	ram2kDev.nDataBytesPerChunk = nandemul2k_GetBytesPerChunk();
+	ram2kDev.totalBytesPerChunk = nandemul2k_GetBytesPerChunk();
 	ram2kDev.nChunksPerBlock = nandemul2k_GetChunksPerBlock();
 	ram2kDev.nReservedBlocks = 5;
 	ram2kDev.startBlock = 0; // First block after /boot
--- a/direct/yaffsfs.c
+++ b/direct/yaffsfs.c
@@ -31,7 +31,7 @@ static yaffsfs_DeviceConfiguration *yaff
 
 
 /* Some forward references */
-static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path, int symDepth);
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path, int symDepth);
 static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj);
 
 
@@ -137,22 +137,95 @@ static int yaffsfs_PutHandle(int handle)
 // Stuff to search for a directory from a path
 
 
-int yaffsfs_Match(char a, char b)
+int yaffsfs_Match(YCHAR a, YCHAR b)
 {
 	// case sensitive
 	return (a == b);
 }
 
+int yaffsfs_IsPathDivider(YCHAR ch)
+{
+	YCHAR *str = YAFFS_PATH_DIVIDERS;
+	
+	while(*str){
+		if(*str == ch)
+			return 1;
+		str++;
+	}
+	
+	return 0;
+}
+
 // yaffsfs_FindDevice
 // yaffsfs_FindRoot
 // Scan the configuration list to find the root.
 // Curveballs: Should match paths that end in '/' too
 // Curveball2 Might have "/x/ and "/x/y". Need to return the longest match
-static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
+static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath)
 {
 	yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
-	const char *leftOver;
-	const char *p;
+	const YCHAR *leftOver;
+	const YCHAR *p;
+	yaffs_Device *retval = NULL;
+	int thisMatchLength;
+	int longestMatch = -1;
+	
+	// Check all configs, choose the one that:
+	// 1) Actually matches a prefix (ie /a amd /abc will not match
+	// 2) Matches the longest.
+	while(cfg && cfg->prefix && cfg->dev)
+	{
+		leftOver = path;
+		p = cfg->prefix;
+		thisMatchLength = 0;
+		
+		
+		// Strip off any leading /'s
+		
+		while(yaffsfs_IsPathDivider(*p))
+			p++;
+
+		while(yaffsfs_IsPathDivider(*leftOver))
+			leftOver++;
+			
+		while(*p && *leftOver && 
+		      yaffsfs_Match(*p,*leftOver))
+		{
+			p++;
+			leftOver++;
+			thisMatchLength++;
+			
+			// Skip over any multiple /'s to treat them as one or
+			// skip over a trailling / in the prefix, but not the matching string
+			while(yaffsfs_IsPathDivider(*p) &&
+			      (yaffsfs_IsPathDivider(*(p+1)) || !(*(p+1))))
+			      p++;			
+
+			// Only skip over multiple /'s
+			while(yaffsfs_IsPathDivider(*leftOver) &&
+			      yaffsfs_IsPathDivider(*(leftOver+1)))
+			      leftOver++;			
+		}
+		
+		if((!*p ) &&
+		   (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part
+		   (thisMatchLength > longestMatch))
+		{
+			// Matched prefix
+			*restOfPath = (YCHAR *)leftOver;
+			retval = cfg->dev;
+			longestMatch = thisMatchLength;
+		}
+		cfg++;
+	}
+	return retval;
+}
+#if 0
+static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath)
+{
+	yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
+	const YCHAR *leftOver;
+	const YCHAR *p;
 	yaffs_Device *retval = NULL;
 	int thisMatchLength;
 	int longestMatch = -1;
@@ -167,7 +240,7 @@ static yaffs_Device *yaffsfs_FindDevice(
 		thisMatchLength = 0;
 		
 		while(*p &&  //unmatched part of prefix 
-		      strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end)
+		      !(yaffsfs_IsPathDivider(*p) && (p[1] == 0)) && // the rest of the prefix is not / (to catch / at end)
 		      *leftOver && 
 		      yaffsfs_Match(*p,*leftOver))
 		{
@@ -175,12 +248,14 @@ static yaffs_Device *yaffsfs_FindDevice(
 			leftOver++;
 			thisMatchLength++;
 		}
-		if((!*p || strcmp(p,"/") == 0) &&      // end of prefix
-		   (!*leftOver || *leftOver == '/') && // no more in this path name part
+		
+
+		if((!*p || (yaffsfs_IsPathDivider(*p) && (p[1] == 0))) &&      // end of prefix
+		   (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part
 		   (thisMatchLength > longestMatch))
 		{
 			// Matched prefix
-			*restOfPath = (char *)leftOver;
+			*restOfPath = (YCHAR *)leftOver;
 			retval = cfg->dev;
 			longestMatch = thisMatchLength;
 		}
@@ -188,8 +263,9 @@ static yaffs_Device *yaffsfs_FindDevice(
 	}
 	return retval;
 }
+#endif
 
-static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath)
+static yaffs_Object *yaffsfs_FindRoot(const YCHAR *path, YCHAR **restOfPath)
 {
 
 	yaffs_Device *dev;
@@ -207,9 +283,9 @@ static yaffs_Object *yaffsfs_FollowLink(
 
 	while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
 	{
-		char *alias = obj->variant.symLinkVariant.alias;
+		YCHAR *alias = obj->variant.symLinkVariant.alias;
 						
-		if(*alias == '/')
+		if(yaffsfs_IsPathDivider(*alias))
 		{
 			// Starts with a /, need to scan from root up
 			obj = yaffsfs_FindObject(NULL,alias,symDepth++);
@@ -228,11 +304,11 @@ static yaffs_Object *yaffsfs_FollowLink(
 // Parse a path to determine the directory and the name within the directory.
 //
 // eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"
-static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *path,char **name,int symDepth)
+static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const YCHAR *path,YCHAR **name,int symDepth)
 {
 	yaffs_Object *dir;
-	char *restOfPath;
-	char str[YAFFS_MAX_NAME_LENGTH+1];
+	YCHAR *restOfPath;
+	YCHAR str[YAFFS_MAX_NAME_LENGTH+1];
 	int i;
 	
 	if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES)
@@ -243,7 +319,7 @@ static yaffs_Object *yaffsfs_DoFindDirec
 	if(startDir)
 	{
 		dir = startDir;
-		restOfPath = (char *)path;
+		restOfPath = (YCHAR *)path;
 	}
 	else
 	{
@@ -255,7 +331,7 @@ static yaffs_Object *yaffsfs_DoFindDirec
 		// parse off /.
 		// curve ball: also throw away surplus '/' 
 		// eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
-		while(*restOfPath == '/')
+		while(yaffsfs_IsPathDivider(*restOfPath))
 		{
 			restOfPath++; // get rid of '/'
 		}
@@ -263,7 +339,7 @@ static yaffs_Object *yaffsfs_DoFindDirec
 		*name = restOfPath;
 		i = 0;
 		
-		while(*restOfPath && *restOfPath != '/')
+		while(*restOfPath && !yaffsfs_IsPathDivider(*restOfPath))
 		{
 			if (i < YAFFS_MAX_NAME_LENGTH)
 			{
@@ -281,11 +357,11 @@ static yaffs_Object *yaffsfs_DoFindDirec
 		}
 		else
 		{
-			if(strcmp(str,".") == 0)
+			if(yaffs_strcmp(str,_Y(".")) == 0)
 			{
 				// Do nothing
 			}
-			else if(strcmp(str,"..") == 0)
+			else if(yaffs_strcmp(str,_Y("..")) == 0)
 			{
 				dir = dir->parent;
 			}
@@ -311,17 +387,17 @@ static yaffs_Object *yaffsfs_DoFindDirec
 	return NULL;
 }
 
-static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const char *path,char **name,int symDepth)
+static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const YCHAR *path,YCHAR **name,int symDepth)
 {
 	return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth);
 }
 
 // yaffsfs_FindObject turns a path for an existing object into the object
 // 
-static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path,int symDepth)
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path,int symDepth)
 {
 	yaffs_Object *dir;
-	char *name;
+	YCHAR *name;
 	
 	dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth);
 	
@@ -334,12 +410,39 @@ static yaffs_Object *yaffsfs_FindObject(
 }
 
 
+int yaffs_dup(int fd)
+{
+	int newHandle = -1;
+	yaffsfs_Handle *oldPtr = NULL;
+	yaffsfs_Handle *newPtr = NULL;
+	
+	yaffsfs_Lock();
+	
+	oldPtr = yaffsfs_GetHandlePointer(fd);
+	if(oldPtr && oldPtr->inUse)
+		newHandle = yaffsfs_GetHandle();
+	if(newHandle >= 0)
+		newPtr = yaffsfs_GetHandlePointer(newHandle);
+		
+	if(newPtr){
+		*newPtr = *oldPtr;
+		return newHandle;
+	}
+	
+	if(!oldPtr)
+		yaffsfs_SetError(-EBADF);
+	else
+		yaffsfs_SetError(-ENOMEM);
+	
+	return -1;
+		
+}
 
-int yaffs_open(const char *path, int oflag, int mode)
+int yaffs_open(const YCHAR *path, int oflag, int mode)
 {
 	yaffs_Object *obj = NULL;
 	yaffs_Object *dir = NULL;
-	char *name;
+	YCHAR *name;
 	int handle = -1;
 	yaffsfs_Handle *h = NULL;
 	int alreadyOpen = 0;
@@ -373,6 +476,11 @@ int yaffs_open(const char *path, int ofl
 			obj = yaffsfs_FollowLink(obj,symDepth++);
 		}
 
+		if(obj && obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+		{
+			obj = NULL;
+		}
+
 		if(obj)
 		{
 			// Check if the object is already in use
@@ -438,6 +546,7 @@ int yaffs_open(const char *path, int ofl
 			else
 			{
 				yaffsfs_SetError(-ENOTDIR);
+				errorReported = 1;
 			}
 		}
 		
@@ -463,17 +572,43 @@ int yaffs_open(const char *path, int ofl
 			yaffsfs_PutHandle(handle);
 			if(!errorReported)
 			{
-				yaffsfs_SetError(-EACCESS);
+				yaffsfs_SetError(-EACCES);
 				errorReported = 1;
 			}
 			handle = -1;
 		}
-		
+
+	}
+
+	yaffsfs_Unlock();
+
+	return handle;
+}
+
+int yaffs_flush(int fd)
+{
+	yaffsfs_Handle *h = NULL;
+	int retVal = 0;
+
+	yaffsfs_Lock();
+
+	h = yaffsfs_GetHandlePointer(fd);
+
+	if(h && h->inUse)
+	{
+		// flush the file
+		yaffs_FlushFile(h->obj,1);
+	}
+	else
+	{
+		// bad handle
+		yaffsfs_SetError(-EBADF);
+		retVal = -1;
 	}
 	
 	yaffsfs_Unlock();
-	
-	return handle;		
+
+	return retVal;
 }
 
 int yaffs_close(int fd)
@@ -515,7 +650,7 @@ int yaffs_read(int fd, void *buf, unsign
 	yaffs_Object *obj = NULL;
 	int pos = 0;
 	int nRead = -1;
-	int maxRead;
+	unsigned int maxRead;
 	
 	yaffsfs_Lock();
 	h = yaffsfs_GetHandlePointer(fd);
@@ -570,6 +705,59 @@ int yaffs_read(int fd, void *buf, unsign
 		
 }
 
+int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset)
+{
+	yaffsfs_Handle *h = NULL;
+	yaffs_Object *obj = NULL;
+	int pos = 0;
+	int nRead = -1;
+	unsigned int maxRead;
+	
+	yaffsfs_Lock();
+	h = yaffsfs_GetHandlePointer(fd);
+	obj = yaffsfs_GetHandleObject(fd);
+	
+	if(!h || !obj)
+	{
+		// bad handle
+		yaffsfs_SetError(-EBADF);		
+	}
+	else if( h && obj)
+	{
+		pos= offset;
+		if(yaffs_GetObjectFileLength(obj) > pos)
+		{
+			maxRead = yaffs_GetObjectFileLength(obj) - pos;
+		}
+		else
+		{
+			maxRead = 0;
+		}
+
+		if(nbyte > maxRead)
+		{
+			nbyte = maxRead;
+		}
+
+		
+		if(nbyte > 0)
+		{
+			nRead = yaffs_ReadDataFromFile(obj,buf,pos,nbyte);
+		}
+		else
+		{
+			nRead = 0;
+		}
+		
+	}
+	
+	yaffsfs_Unlock();
+	
+	
+	return (nRead >= 0) ? nRead : -1;
+		
+}
+
 int yaffs_write(int fd, const void *buf, unsigned int nbyte)
 {
 	yaffsfs_Handle *h = NULL;
@@ -622,7 +810,77 @@ int yaffs_write(int fd, const void *buf,
 
 }
 
-int yaffs_truncate(int fd, off_t newSize)
+int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset)
+{
+	yaffsfs_Handle *h = NULL;
+	yaffs_Object *obj = NULL;
+	int pos = 0;
+	int nWritten = -1;
+	int writeThrough = 0;
+	
+	yaffsfs_Lock();
+	h = yaffsfs_GetHandlePointer(fd);
+	obj = yaffsfs_GetHandleObject(fd);
+	
+	if(!h || !obj)
+	{
+		// bad handle
+		yaffsfs_SetError(-EBADF);		
+	}
+	else if( h && obj && h->readOnly)
+	{
+		// todo error
+	}
+	else if( h && obj)
+	{
+		pos = offset;
+				
+		nWritten = yaffs_WriteDataToFile(obj,buf,pos,nbyte,writeThrough);
+		
+		if(nWritten < nbyte)
+			yaffsfs_SetError(-ENOSPC);
+		
+	}
+	
+	yaffsfs_Unlock();
+	
+	
+	return (nWritten >= 0) ? nWritten : -1;
+
+}
+
+
+int yaffs_truncate(const YCHAR *path,off_t newSize) 
+{
+	yaffs_Object *obj = NULL;
+	int result = YAFFS_FAIL;
+	
+	yaffsfs_Lock();
+
+	obj = yaffsfs_FindObject(NULL,path,0);
+	if(obj)
+		obj = yaffs_GetEquivalentObject(obj);
+
+	if(!obj)
+	{
+		yaffsfs_SetError(-ENOENT);
+	}
+	else if(obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+	{
+		yaffsfs_SetError(-EISDIR);
+	}
+	else
+	{
+		result = yaffs_ResizeFile(obj,newSize);
+	}
+	
+	yaffsfs_Unlock();
+	
+	
+	return (result) ? 0 : -1;
+}
+
+int yaffs_ftruncate(int fd, off_t newSize)
 {
 	yaffsfs_Handle *h = NULL;
 	yaffs_Object *obj = NULL;
@@ -704,11 +962,11 @@ off_t yaffs_lseek(int fd, off_t offset, 
 }
 
 
-int yaffsfs_DoUnlink(const char *path,int isDirectory) 
+int yaffsfs_DoUnlink(const YCHAR *path,int isDirectory) 
 {
 	yaffs_Object *dir = NULL;
 	yaffs_Object *obj = NULL;
-	char *name;
+	YCHAR *name;
 	int result = YAFFS_FAIL;
 	
 	yaffsfs_Lock();
@@ -747,23 +1005,25 @@ int yaffsfs_DoUnlink(const char *path,in
 	
 	return (result == YAFFS_FAIL) ? -1 : 0;
 }
-int yaffs_rmdir(const char *path) 
+
+
+int yaffs_rmdir(const YCHAR *path) 
 {
 	return yaffsfs_DoUnlink(path,1);
 }
 
-int yaffs_unlink(const char *path) 
+int yaffs_unlink(const YCHAR *path) 
 {
 	return yaffsfs_DoUnlink(path,0);
 }
 
-int yaffs_rename(const char *oldPath, const char *newPath)
+int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
 {
 	yaffs_Object *olddir = NULL;
 	yaffs_Object *newdir = NULL;
 	yaffs_Object *obj = NULL;
-	char *oldname;
-	char *newname;
+	YCHAR *oldname;
+	YCHAR *newname;
 	int result= YAFFS_FAIL;
 	int renameAllowed = 1;
 	
@@ -802,7 +1062,7 @@ int yaffs_rename(const char *oldPath, co
 			}
 			xx = xx->parent;
 		}
-		if(!renameAllowed) yaffsfs_SetError(-EACCESS);
+		if(!renameAllowed) yaffsfs_SetError(-EACCES);
 	}
 	
 	if(renameAllowed)
@@ -851,15 +1111,24 @@ static int yaffsfs_DoStat(yaffs_Object *
     	buf->st_size = yaffs_GetObjectFileLength(obj);
 		buf->st_blksize = obj->myDev->nDataBytesPerChunk;
     	buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize;
-    	buf->yst_atime = obj->yst_atime; 
-    	buf->yst_ctime = obj->yst_ctime; 
-    	buf->yst_mtime = obj->yst_mtime; 
+#if CONFIG_YAFFS_WINCE
+		buf->yst_wince_atime[0] = obj->win_atime[0];
+		buf->yst_wince_atime[1] = obj->win_atime[1];
+		buf->yst_wince_ctime[0] = obj->win_ctime[0];
+		buf->yst_wince_ctime[1] = obj->win_ctime[1];
+		buf->yst_wince_mtime[0] = obj->win_mtime[0];
+		buf->yst_wince_mtime[1] = obj->win_mtime[1];
+#else
+    	buf->yst_atime = obj->yst_atime;
+    	buf->yst_ctime = obj->yst_ctime;
+    	buf->yst_mtime = obj->yst_mtime;
+#endif
 		retVal = 0;
 	}
 	return retVal;
 }
 
-static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int doLStat)
+static int yaffsfs_DoStatOrLStat(const YCHAR *path, struct yaffs_stat *buf,int doLStat)
 {
 	yaffs_Object *obj;
 	
@@ -889,12 +1158,12 @@ static int yaffsfs_DoStatOrLStat(const c
 	
 }
 
-int yaffs_stat(const char *path, struct yaffs_stat *buf)
+int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf)
 {
 	return yaffsfs_DoStatOrLStat(path,buf,0);
 }
 
-int yaffs_lstat(const char *path, struct yaffs_stat *buf)
+int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf)
 {
 	return yaffsfs_DoStatOrLStat(path,buf,1);
 }
@@ -915,6 +1184,46 @@ int yaffs_fstat(int fd, struct yaffs_sta
 	else
 	{
 		// bad handle
+		yaffsfs_SetError(-EBADF);
+	}
+
+	yaffsfs_Unlock();
+
+	return retVal;
+}
+
+#ifdef CONFIG_YAFFS_WINCE
+int yaffs_get_wince_times(int fd, unsigned *wctime, unsigned *watime, unsigned *wmtime)
+{
+	yaffs_Object *obj;
+
+	int retVal = -1;
+
+	yaffsfs_Lock();
+	obj = yaffsfs_GetHandleObject(fd);
+
+	if(obj)
+	{
+
+		if(wctime){
+			wctime[0] = obj->win_ctime[0];
+			wctime[1] = obj->win_ctime[1];
+		}
+		if(watime){
+			watime[0] = obj->win_atime[0];
+			watime[1] = obj->win_atime[1];
+		}
+		if(wmtime){
+			wmtime[0] = obj->win_mtime[0];
+			wmtime[1] = obj->win_mtime[1];
+		}
+
+
+		retVal = 0;
+	}
+	else
+	{
+		// bad handle
 		yaffsfs_SetError(-EBADF);		
 	}
 	
@@ -923,6 +1232,51 @@ int yaffs_fstat(int fd, struct yaffs_sta
 	return retVal;
 }
 
+
+int yaffs_set_wince_times(int fd, 
+						  const unsigned *wctime, 
+						  const unsigned *watime, 
+						  const unsigned *wmtime)
+{
+	yaffs_Object *obj;
+	
+	int retVal = -1;
+
+	yaffsfs_Lock();
+	obj = yaffsfs_GetHandleObject(fd);
+
+	if(obj)
+	{
+
+		if(wctime){
+			obj->win_ctime[0] = wctime[0];
+			obj->win_ctime[1] = wctime[1];
+		}
+		if(watime){
+			obj->win_atime[0] = watime[0];
+			obj->win_atime[1] = watime[1];
+		}
+		if(wctime){
+			obj->win_mtime[0] = wmtime[0];
+			obj->win_mtime[1] = wmtime[1];
+		}
+
+		retVal = 0;
+	}
+	else
+	{
+		// bad handle
+		yaffsfs_SetError(-EBADF);
+	}
+
+	yaffsfs_Unlock();
+
+	return retVal;
+}
+
+#endif
+
+
 static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode)
 {
 	int result;
@@ -943,7 +1297,46 @@ static int yaffsfs_DoChMod(yaffs_Object 
 }
 
 
-int yaffs_chmod(const char *path, mode_t mode)
+int yaffs_access(const YCHAR *path, int amode)
+{
+	yaffs_Object *obj;
+	
+	int retval = 0;
+	
+	yaffsfs_Lock();
+	obj = yaffsfs_FindObject(NULL,path,0);
+	
+	if(obj)
+	{
+		int access_ok = 1;
+		
+		if((amode & R_OK) && !(obj->yst_mode & S_IREAD))
+			access_ok = 0;
+		if((amode & W_OK) && !(obj->yst_mode & S_IWRITE))
+			access_ok = 0;
+		if((amode & X_OK) && !(obj->yst_mode & S_IEXEC))
+			access_ok = 0;
+
+		if(!access_ok) {
+			yaffsfs_SetError(-EACCES);
+			retval = -1;
+		}
+	}
+	else
+	{
+		// todo error not found
+		yaffsfs_SetError(-ENOENT);
+		retval = -1;
+	}
+	
+	yaffsfs_Unlock();
+	
+	return retval;
+	
+}
+
+
+int yaffs_chmod(const YCHAR *path, mode_t mode)
 {
 	yaffs_Object *obj;
 	
@@ -994,11 +1387,11 @@ int yaffs_fchmod(int fd, mode_t mode)
 }
 
 
-int yaffs_mkdir(const char *path, mode_t mode)
+int yaffs_mkdir(const YCHAR *path, mode_t mode)
 {
 	yaffs_Object *parent = NULL;
 	yaffs_Object *dir = NULL;
-	char *name;
+	YCHAR *name;
 	int retVal= -1;
 	
 	yaffsfs_Lock();
@@ -1011,7 +1404,14 @@ int yaffs_mkdir(const char *path, mode_t
 	}
 	else
 	{
-		yaffsfs_SetError(-ENOSPC); // just assume no space for now
+		if(!parent){
+			yaffsfs_SetError(-ENOENT); // missing path
+		}
+		else if (yaffs_FindObjectByName(parent,name)){
+			yaffsfs_SetError(-EEXIST); // the name already exists
+		}
+		else
+			yaffsfs_SetError(-ENOSPC); // just assume no space 
 		retVal = -1;
 	}
 	
@@ -1020,14 +1420,14 @@ int yaffs_mkdir(const char *path, mode_t
 	return retVal;
 }
 
-int yaffs_mount(const char *path)
+int yaffs_mount(const YCHAR *path)
 {
 	int retVal=-1;
 	int result=YAFFS_FAIL;
 	yaffs_Device *dev=NULL;
-	char *dummy;
+	YCHAR *dummy;
 	
-	T(YAFFS_TRACE_ALWAYS,("yaffs: Mounting %s\n",path));
+	T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Mounting %s" TENDSTR),path));
 	
 	yaffsfs_Lock();
 	dev = yaffsfs_FindDevice(path,&dummy);
@@ -1060,11 +1460,46 @@ int yaffs_mount(const char *path)
 	
 }
 
-int yaffs_unmount(const char *path)
+int yaffs_sync(const YCHAR *path)
 {
 	int retVal=-1;
 	yaffs_Device *dev=NULL;
-	char *dummy;
+	YCHAR *dummy;
+	
+	yaffsfs_Lock();
+	dev = yaffsfs_FindDevice(path,&dummy);
+	if(dev)
+	{
+		if(dev->isMounted)
+		{
+			
+			yaffs_FlushEntireDeviceCache(dev);
+			yaffs_CheckpointSave(dev);
+			
+			
+		}
+		else
+		{
+			//todo error - not mounted.
+			yaffsfs_SetError(-EINVAL);
+			
+		}
+	}
+	else
+	{
+		// todo error - no device
+		yaffsfs_SetError(-ENODEV);
+	}	
+	yaffsfs_Unlock();
+	return retVal;	
+}
+
+
+int yaffs_unmount(const YCHAR *path)
+{
+	int retVal=-1;
+	yaffs_Device *dev=NULL;
+	YCHAR *dummy;
 	
 	yaffsfs_Lock();
 	dev = yaffsfs_FindDevice(path,&dummy);
@@ -1116,11 +1551,11 @@ int yaffs_unmount(const char *path)
 	
 }
 
-loff_t yaffs_freespace(const char *path)
+loff_t yaffs_freespace(const YCHAR *path)
 {
 	loff_t retVal=-1;
 	yaffs_Device *dev=NULL;
-	char *dummy;
+	YCHAR *dummy;
 	
 	yaffsfs_Lock();
 	dev = yaffsfs_FindDevice(path,&dummy);
@@ -1128,7 +1563,31 @@ loff_t yaffs_freespace(const char *path)
 	{
 		retVal = yaffs_GetNumberOfFreeChunks(dev);
 		retVal *= dev->nDataBytesPerChunk;
-		
+
+	}
+	else
+	{
+		yaffsfs_SetError(-EINVAL);
+	}
+
+	yaffsfs_Unlock();
+	return retVal;
+}
+
+loff_t yaffs_totalspace(const YCHAR *path)
+{
+	loff_t retVal=-1;
+	yaffs_Device *dev=NULL;
+	YCHAR *dummy;
+
+	yaffsfs_Lock();
+	dev = yaffsfs_FindDevice(path,&dummy);
+	if(dev  && dev->isMounted)
+	{
+		retVal = (dev->endBlock - dev->startBlock + 1) - dev->nReservedBlocks;
+		retVal *= dev->nChunksPerBlock;
+		retVal *= dev->nDataBytesPerChunk;
+
 	}
 	else
 	{
@@ -1176,16 +1635,16 @@ typedef struct
 {
 	__u32 magic;
 	yaffs_dirent de;		/* directory entry being used by this dsc */
-	char name[NAME_MAX+1];		/* name of directory being searched */
+	YCHAR name[NAME_MAX+1];		/* name of directory being searched */
 	yaffs_Object *dirObj;		/* ptr to directory being searched */
 	yaffs_Object *nextReturn;	/* obj to be returned by next readddir */
 	int offset;
-	struct list_head others;	
+	struct ylist_head others;	
 } yaffsfs_DirectorySearchContext;
 
 
 
-static struct list_head search_contexts;
+static struct ylist_head search_contexts;
 
 
 static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc)
@@ -1196,10 +1655,10 @@ static void yaffsfs_SetDirRewound(yaffsf
 	   
 	   dsc->offset = 0;
 	   
-	   if( list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+	   if( ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){
 	   	dsc->nextReturn = NULL;
 	   } else {
-	      	dsc->nextReturn = list_entry(dsc->dirObj->variant.directoryVariant.children.next,
+	      	dsc->nextReturn = ylist_entry(dsc->dirObj->variant.directoryVariant.children.next,
 						yaffs_Object,siblings);
 	   }
 	} else {
@@ -1214,15 +1673,15 @@ static void yaffsfs_DirAdvance(yaffsfs_D
 	   dsc->dirObj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY){
 	   
 	   if( dsc->nextReturn == NULL ||
-	       list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+	       ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){
 	   	dsc->nextReturn = NULL;
 	   } else {
-		   struct list_head *next = dsc->nextReturn->siblings.next;
+		   struct ylist_head *next = dsc->nextReturn->siblings.next;
    
 		   if( next == &dsc->dirObj->variant.directoryVariant.children)
 	   		dsc->nextReturn = NULL; /* end of list */
 	   	   else 
-		   	dsc->nextReturn = list_entry(next,yaffs_Object,siblings);
+		   	dsc->nextReturn = ylist_entry(next,yaffs_Object,siblings);
 	   }
 	} else {
 		/* Hey someone isn't playing nice! */
@@ -1232,20 +1691,20 @@ static void yaffsfs_DirAdvance(yaffsfs_D
 static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj)
 {
 
-	struct list_head *i;
+	struct ylist_head *i;
 	yaffsfs_DirectorySearchContext *dsc;
 	
 	/* if search contexts not initilised then skip */
 	if(!search_contexts.next)
 		return;
 		
-	/* Iteratethrough the directory search contexts.
+	/* Iterate through the directory search contexts.
 	 * If any are the one being removed, then advance the dsc to
 	 * the next one to prevent a hanging ptr.
 	 */
-	 list_for_each(i, &search_contexts) {
+	 ylist_for_each(i, &search_contexts) {
 		if (i) {
-			dsc = list_entry(i, yaffsfs_DirectorySearchContext,others);
+			dsc = ylist_entry(i, yaffsfs_DirectorySearchContext,others);
 			if(dsc->nextReturn == obj)
 				yaffsfs_DirAdvance(dsc);
 		}
@@ -1253,7 +1712,7 @@ static void yaffsfs_RemoveObjectCallback
 				
 }
 
-yaffs_DIR *yaffs_opendir(const char *dirname)
+yaffs_DIR *yaffs_opendir(const YCHAR *dirname)
 {
 	yaffs_DIR *dir = NULL;
  	yaffs_Object *obj = NULL;
@@ -1273,13 +1732,13 @@ yaffs_DIR *yaffs_opendir(const char *dir
 			memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext));
 			dsc->magic = YAFFS_MAGIC;
 			dsc->dirObj = obj;
-			strncpy(dsc->name,dirname,NAME_MAX);
-			INIT_LIST_HEAD(&dsc->others);
+			yaffs_strncpy(dsc->name,dirname,NAME_MAX);
+			YINIT_LIST_HEAD(&dsc->others);
 			
 			if(!search_contexts.next)
-				INIT_LIST_HEAD(&search_contexts);
+				YINIT_LIST_HEAD(&search_contexts);
 				
-			list_add(&dsc->others,&search_contexts);	
+			ylist_add(&dsc->others,&search_contexts);	
 			yaffsfs_SetDirRewound(dsc);		}
 	
 	}
@@ -1303,10 +1762,10 @@ struct yaffs_dirent *yaffs_readdir(yaffs
 			dsc->de.d_dont_use = (unsigned)dsc->nextReturn;
 			dsc->de.d_off = dsc->offset++;
 			yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX);
-			if(strlen(dsc->de.d_name) == 0)
+			if(yaffs_strlen(dsc->de.d_name) == 0)
 			{
 				// this should not happen!
-				strcpy(dsc->de.d_name,"zz");
+				yaffs_strcpy(dsc->de.d_name,_Y("zz"));
 			}
 			dsc->de.d_reclen = sizeof(struct yaffs_dirent);
 			retVal = &dsc->de;
@@ -1344,7 +1803,7 @@ int yaffs_closedir(yaffs_DIR *dirp)
 		
 	yaffsfs_Lock();
 	dsc->magic = 0;
-	list_del(&dsc->others); /* unhook from list */
+	ylist_del(&dsc->others); /* unhook from list */
 	YFREE(dsc);
 	yaffsfs_Unlock();
 	return 0;
@@ -1353,11 +1812,11 @@ int yaffs_closedir(yaffs_DIR *dirp)
 // end of directory stuff
 
 
-int yaffs_symlink(const char *oldpath, const char *newpath)
+int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath)
 {
 	yaffs_Object *parent = NULL;
 	yaffs_Object *obj;
-	char *name;
+	YCHAR *name;
 	int retVal= -1;
 	int mode = 0; // ignore for now
 	
@@ -1380,7 +1839,7 @@ int yaffs_symlink(const char *oldpath, c
 	
 }
 
-int yaffs_readlink(const char *path, char *buf, int bufsiz)
+int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz)
 {
 	yaffs_Object *obj = NULL;
 	int retVal;
@@ -1402,16 +1861,16 @@ int yaffs_readlink(const char *path, cha
 	}
 	else
 	{
-		char *alias = obj->variant.symLinkVariant.alias;
+		YCHAR *alias = obj->variant.symLinkVariant.alias;
 		memset(buf,0,bufsiz);
-		strncpy(buf,alias,bufsiz - 1);
+		yaffs_strncpy(buf,alias,bufsiz - 1);
 		retVal = 0;
 	}
 	yaffsfs_Unlock();
 	return retVal;
 }
 
-int yaffs_link(const char *oldpath, const char *newpath)
+int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath)
 {
 	// Creates a link called newpath to existing oldpath
 	yaffs_Object *obj = NULL;
@@ -1439,7 +1898,7 @@ int yaffs_link(const char *oldpath, cons
 		yaffs_Object *newdir = NULL;
 		yaffs_Object *link = NULL;
 		
-		char *newname;
+		YCHAR *newname;
 		
 		newdir = yaffsfs_FindDirectory(NULL,newpath,&newname,0);
 		
@@ -1453,7 +1912,7 @@ int yaffs_link(const char *oldpath, cons
 			yaffsfs_SetError(-EXDEV);
 			retVal = -1;
 		}
-		if(newdir && strlen(newname) > 0)
+		if(newdir && yaffs_strlen(newname) > 0)
 		{
 			link = yaffs_Link(newdir,newname,obj);
 			if(link)
@@ -1471,11 +1930,12 @@ int yaffs_link(const char *oldpath, cons
 	return retVal;
 }
 
-int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev);
 
-int yaffs_DumpDevStruct(const char *path)
+int yaffs_DumpDevStruct(const YCHAR *path)
 {
-	char *rest;
+#if 0
+	YCHAR *rest;
 	
 	yaffs_Object *obj = yaffsfs_FindRoot(path,&rest);
 	
@@ -1500,6 +1960,8 @@ int yaffs_DumpDevStruct(const char *path
 		);
 		
 	}
+
+#endif
 	return 0;
 }
 
--- a/direct/yaffsfs.h
+++ b/direct/yaffsfs.h
@@ -35,6 +35,9 @@
 #define NAME_MAX	256
 #endif
 
+
+#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES
+
 #ifndef O_RDONLY
 #define O_RDONLY	00
 #endif
@@ -91,8 +94,8 @@
 #define EBADF	9
 #endif
 
-#ifndef EACCESS
-#define EACCESS	13
+#ifndef EACCES
+#define EACCES	13
 #endif
 
 #ifndef EXDEV	
@@ -154,14 +157,30 @@
 #define	S_IWRITE	0000200
 #endif
 
+#ifndef S_IEXEC
+#define	S_IEXEC	0000100
+#endif
 
+#ifndef R_OK
+#define R_OK	4
+#define W_OK	2
+#define X_OK	1
+#define F_OK	0
+#endif
+
+#else
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
 
 
 struct yaffs_dirent{
     long d_ino;                 /* inode number */
     off_t d_off;                /* offset to this dirent */
     unsigned short d_reclen;    /* length of this d_name */
-    char d_name [NAME_MAX+1];   /* file name (null-terminated) */
+    YUCHAR  d_type;	/* type of this record */
+    YCHAR d_name [NAME_MAX+1];   /* file name (null-terminated) */
     unsigned d_dont_use;	/* debug pointer, not for public consumption */
 };
 
@@ -175,7 +194,7 @@ typedef struct __opaque yaffs_DIR;
 struct yaffs_stat{
     int		      st_dev;      /* device */
     int           st_ino;      /* inode */
-    mode_t        st_mode;     /* protection */
+    unsigned      st_mode;     /* protection */
     int           st_nlink;    /* number of hard links */
     int           st_uid;      /* user ID of owner */
     int           st_gid;      /* group ID of owner */
@@ -183,46 +202,68 @@ struct yaffs_stat{
     off_t         st_size;     /* total size, in bytes */
     unsigned long st_blksize;  /* blocksize for filesystem I/O */
     unsigned long st_blocks;   /* number of blocks allocated */
-    unsigned long yst_atime;    /* time of last access */
+#ifdef CONFIG_YAFFS_WINCE
+	/* Special 64-bit times for WinCE */
+	unsigned long yst_wince_atime[2];
+	unsigned long yst_wince_mtime[2];
+	unsigned long yst_wince_ctime[2];
+#else
+	unsigned long yst_atime;    /* time of last access */
     unsigned long yst_mtime;    /* time of last modification */
     unsigned long yst_ctime;    /* time of last change */
+#endif
 };
 
-int yaffs_open(const char *path, int oflag, int mode) ;
+int yaffs_open(const YCHAR *path, int oflag, int mode) ;
+int yaffs_close(int fd) ;
+int yaffs_flush(int fd) ;
+
+int yaffs_access(const YCHAR *path, int amode);
+
+int yaffs_dup(int fd);
+
 int yaffs_read(int fd, void *buf, unsigned int nbyte) ;
 int yaffs_write(int fd, const void *buf, unsigned int nbyte) ;
-int yaffs_close(int fd) ;
+
+int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset);
+int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset);
+
 off_t yaffs_lseek(int fd, off_t offset, int whence) ;
-int yaffs_truncate(int fd, off_t newSize);
 
-int yaffs_unlink(const char *path) ;
-int yaffs_rename(const char *oldPath, const char *newPath) ;
+int yaffs_truncate(const YCHAR *path, off_t newSize);
+int yaffs_ftruncate(int fd, off_t newSize);
 
-int yaffs_stat(const char *path, struct yaffs_stat *buf) ;
-int yaffs_lstat(const char *path, struct yaffs_stat *buf) ;
+int yaffs_unlink(const YCHAR *path) ;
+int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) ;
+
+int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf) ;
+int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf) ;
 int yaffs_fstat(int fd, struct yaffs_stat *buf) ;
 
-int yaffs_chmod(const char *path, mode_t mode); 
+int yaffs_chmod(const YCHAR *path, mode_t mode); 
 int yaffs_fchmod(int fd, mode_t mode); 
 
-int yaffs_mkdir(const char *path, mode_t mode) ;
-int yaffs_rmdir(const char *path) ;
+int yaffs_mkdir(const YCHAR *path, mode_t mode) ;
+int yaffs_rmdir(const YCHAR *path) ;
 
-yaffs_DIR *yaffs_opendir(const char *dirname) ;
+yaffs_DIR *yaffs_opendir(const YCHAR *dirname) ;
 struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) ;
 void yaffs_rewinddir(yaffs_DIR *dirp) ;
 int yaffs_closedir(yaffs_DIR *dirp) ;
 
-int yaffs_mount(const char *path) ;
-int yaffs_unmount(const char *path) ;
+int yaffs_mount(const YCHAR *path) ;
+int yaffs_unmount(const YCHAR *path) ;
+
+int yaffs_sync(const YCHAR *path) ;
 
-int yaffs_symlink(const char *oldpath, const char *newpath); 
-int yaffs_readlink(const char *path, char *buf, int bufsiz); 
+int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath); 
+int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz); 
 
-int yaffs_link(const char *oldpath, const char *newpath); 
-int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath); 
+int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev);
 
-loff_t yaffs_freespace(const char *path);
+loff_t yaffs_freespace(const YCHAR *path);
+loff_t yaffs_totalspace(const YCHAR *path);
 
 void yaffs_initialise(yaffsfs_DeviceConfiguration *configList);
 
--- a/direct/ydirectenv.h
+++ b/direct/ydirectenv.h
@@ -30,7 +30,8 @@
 #include "yaffs_malloc.h"
 
 #include "assert.h"
-#define YBUG() assert(1)
+#define YBUG() assert(0)
+
 
 #define YCHAR char
 #define YUCHAR unsigned char
@@ -42,6 +43,8 @@
 #define yaffs_sprintf	     sprintf
 #define yaffs_toupper(a)     toupper(a)
 
+#define YAFFS_PATH_DIVIDERS  "/"
+
 #ifdef NO_Y_INLINE
 #define Y_INLINE
 #else
--- a/yaffs_checkptrw.c
+++ b/yaffs_checkptrw.c
@@ -16,7 +16,7 @@ const char *yaffs_checkptrw_c_version =
 
 
 #include "yaffs_checkptrw.h"
-
+#include "yaffs_getblockinfo.h"
 
 static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
 {
@@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
 		return 0;
 
 	if(!dev->checkpointBuffer)
-		dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
+		dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
 	if(!dev->checkpointBuffer)
 		return 0;
 
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -53,6 +53,8 @@ extern const char *yaffs_guts_c_version;
 #include <linux/string.h>
 #include <linux/ctype.h>
 
+#include "asm/div64.h"
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 
 #include <linux/statfs.h>	/* Added NCB 15-8-2003 */
@@ -753,6 +755,8 @@ static void yaffs_FillInodeFromObject(st
  		        break;
  		}
 
+ 		inode->i_flags |= S_NOATIME;
+ 		
 		inode->i_ino = obj->objectId;
 		inode->i_mode = obj->yst_mode;
 		inode->i_uid = obj->yst_uid;
@@ -1350,25 +1354,47 @@ static int yaffs_statfs(struct super_blo
 	buf->f_type = YAFFS_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_namelen = 255;
-	if (sb->s_blocksize > dev->nDataBytesPerChunk) {
-
+	
+	if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
+		/* Do this if chunk size is not a power of 2 */
+		
+		uint64_t bytesInDev;
+		uint64_t bytesFree;
+
+		bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
+			     ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
+	
+		do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
+		buf->f_blocks = bytesInDev;
+
+		bytesFree  = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
+			     ((uint64_t)(dev->nDataBytesPerChunk));
+	
+		do_div(bytesFree,sb->s_blocksize);
+	
+		buf->f_bfree = bytesFree;
+	
+	} else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
+	
 		buf->f_blocks =
-		    (dev->endBlock - dev->startBlock +
-		     1) * dev->nChunksPerBlock / (sb->s_blocksize /
-						  dev->nDataBytesPerChunk);
-		buf->f_bfree =
-		    yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
-							dev->nDataBytesPerChunk);
+	                   (dev->endBlock - dev->startBlock + 1) * 
+	                    dev->nChunksPerBlock / 
+	                    (sb->s_blocksize / dev->nDataBytesPerChunk);
+	        buf->f_bfree =
+	                   yaffs_GetNumberOfFreeChunks(dev) / 
+	                   (sb->s_blocksize / dev->nDataBytesPerChunk);
 	} else {
-
-		buf->f_blocks =
-		    (dev->endBlock - dev->startBlock +
-		     1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
-						  sb->s_blocksize);
-		buf->f_bfree =
-		    yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
-							sb->s_blocksize);
+	       buf->f_blocks =
+	                   (dev->endBlock - dev->startBlock + 1) * 
+	                   dev->nChunksPerBlock * 
+	                   (dev->nDataBytesPerChunk / sb->s_blocksize);
+	                   
+	               buf->f_bfree =
+	                   yaffs_GetNumberOfFreeChunks(dev) * 
+	                   (dev->nDataBytesPerChunk / sb->s_blocksize);
 	}
+	
+	
 	buf->f_files = 0;
 	buf->f_ffree = 0;
 	buf->f_bavail = buf->f_bfree;
@@ -1602,6 +1628,7 @@ static struct super_block *yaffs_interna
 
 	sb->s_magic = YAFFS_MAGIC;
 	sb->s_op = &yaffs_super_ops;
+	sb->s_flags |= MS_NOATIME;
 
 	if (!sb)
 		printk(KERN_INFO "yaffs: sb is NULL\n");
@@ -1678,22 +1705,15 @@ static struct super_block *yaffs_interna
 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
 
 	if (yaffsVersion == 1 &&
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-	    mtd->writesize >= 2048) {
-#else
-	    mtd->oobblock >= 2048) {
-#endif
+	    WRITE_SIZE(mtd) >= 2048) {
 	    T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
 	    yaffsVersion = 2;
 	}
 
 	/* Added NCB 26/5/2006 for completeness */
-	if (yaffsVersion == 2 &&
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-	    mtd->writesize == 512) {
-#else
-	    mtd->oobblock == 512) {
-#endif
+	if (yaffsVersion == 2 && 
+	    !options.inband_tags &&
+	    WRITE_SIZE(mtd) == 512){
 	    T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
 	    yaffsVersion = 1;
 	}
@@ -1719,12 +1739,9 @@ static struct super_block *yaffs_interna
 			return NULL;
 		}
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-		if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-#else
-		if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-#endif
-		    mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
+		if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+		    mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
+		    !options.inband_tags) {
 			T(YAFFS_TRACE_ALWAYS,
 			  ("yaffs: MTD device does not have the "
 			   "right page sizes\n"));
@@ -1784,9 +1801,10 @@ static struct super_block *yaffs_interna
 	dev->startBlock = 0;
 	dev->endBlock = nBlocks - 1;
 	dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
-	dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+	dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
 	dev->nReservedBlocks = 5;
 	dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
+	dev->inbandTags = options.inband_tags;
 
 	/* ... and the functions. */
 	if (yaffsVersion == 2) {
@@ -1799,10 +1817,10 @@ static struct super_block *yaffs_interna
 		dev->spareBuffer = YMALLOC(mtd->oobsize);
 		dev->isYaffs2 = 1;
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-		dev->nDataBytesPerChunk = mtd->writesize;
+		dev->totalBytesPerChunk = mtd->writesize;
 		dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
 #else
-		dev->nDataBytesPerChunk = mtd->oobblock;
+		dev->totalBytesPerChunk = mtd->oobblock;
 		dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
 #endif
 		nBlocks = mtd->size / mtd->erasesize;
@@ -1989,6 +2007,7 @@ static char *yaffs_dump_dev(char *buf, y
 {
 	buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
 	buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
+	buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
 	buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
 	buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
 	buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
@@ -2004,10 +2023,8 @@ static char *yaffs_dump_dev(char *buf, y
 	buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
 	buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
 	buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
-	buf +=
-	    sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
-	buf +=
-	    sprintf(buf, "passiveGCs......... %d\n",
+	buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
+	buf += sprintf(buf, "passiveGCs......... %d\n",
 		    dev->passiveGarbageCollections);
 	buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
 	buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
@@ -2023,6 +2040,7 @@ static char *yaffs_dump_dev(char *buf, y
 	    sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
 	buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
 	buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
+	buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
 
 	return buf;
 }
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -19,6 +19,7 @@ const char *yaffs_guts_c_version =
 #include "yaffsinterface.h"
 #include "yaffs_guts.h"
 #include "yaffs_tagsvalidity.h"
+#include "yaffs_getblockinfo.h"
 
 #include "yaffs_tagscompat.h"
 #ifndef  CONFIG_YAFFS_USE_OWN_SORT
@@ -78,9 +79,6 @@ static int yaffs_DoGenericObjectDeletion
 
 static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
 
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
-				    int lineNo);
 
 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
 				  int chunkInNAND);
@@ -121,23 +119,32 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
 
 /* Function to calculate chunk and offset */
 
-static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
-{
-	if(dev->chunkShift){
-		/* Easy-peasy power of 2 case */
-		*chunk  = (__u32)(addr >> dev->chunkShift);
-		*offset = (__u32)(addr & dev->chunkMask);
-	}
-	else if(dev->crumbsPerChunk)
+static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
+{
+	int chunk;
+	__u32 offset;
+	
+	chunk  = (__u32)(addr >> dev->chunkShift);
+		
+	if(dev->chunkDiv == 1)
 	{
-		/* Case where we're using "crumbs" */
-		*offset = (__u32)(addr & dev->crumbMask);
-		addr >>= dev->crumbShift;
-		*chunk = ((__u32)addr)/dev->crumbsPerChunk;
-		*offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
+		/* easy power of 2 case */
+		offset = (__u32)(addr & dev->chunkMask);
 	}
 	else
-		YBUG();
+	{
+		/* Non power-of-2 case */
+		
+		loff_t chunkBase;
+		
+		chunk /= dev->chunkDiv;
+		
+		chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
+		offset = (__u32)(addr - chunkBase);
+	}
+
+	*chunkOut = chunk;
+	*offsetOut = offset;
 }
 
 /* Function to return the number of shifts for a power of 2 greater than or equal
@@ -168,7 +175,7 @@ static __u32 ShiftsGE(__u32 x)
 /* Function to return the number of shifts to get a 1 in bit 0
  */
 
-static __u32 ShiftDiv(__u32 x)
+static __u32 Shifts(__u32 x)
 {
 	int nShifts;
 
@@ -200,16 +207,21 @@ static int yaffs_InitialiseTempBuffers(y
 	for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
 		dev->tempBuffer[i].line = 0;	/* not in use */
 		dev->tempBuffer[i].buffer = buf =
-		    YMALLOC_DMA(dev->nDataBytesPerChunk);
+		    YMALLOC_DMA(dev->totalBytesPerChunk);
 	}
 
 	return buf ? YAFFS_OK : YAFFS_FAIL;
 
 }
 
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
+__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
 {
 	int i, j;
+
+	dev->tempInUse++;
+	if(dev->tempInUse > dev->maxTemp)
+		dev->maxTemp = dev->tempInUse;
+
 	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
 		if (dev->tempBuffer[i].line == 0) {
 			dev->tempBuffer[i].line = lineNo;
@@ -242,10 +254,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D
 
 }
 
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
 				    int lineNo)
 {
 	int i;
+	
+	dev->tempInUse--;
+	
 	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
 		if (dev->tempBuffer[i].buffer == buffer) {
 			dev->tempBuffer[i].line = 0;
@@ -390,11 +405,14 @@ static int yaffs_SkipVerification(yaffs_
 	return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
 }
 
+#if 0
 static int yaffs_SkipFullVerification(yaffs_Device *dev)
 {
 	return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL));
 }
 
+#endif
+
 static int yaffs_SkipNANDVerification(yaffs_Device *dev)
 {
 	return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));
@@ -597,7 +615,6 @@ static int yaffs_VerifyTnodeWorker(yaffs
 	int i;
 	yaffs_Device *dev = obj->myDev;
 	int ok = 1;
-	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
 
 	if (tn) {
 		if (level > 0) {
@@ -646,7 +663,6 @@ static void yaffs_VerifyFile(yaffs_Objec
 	__u32 lastChunk;
 	__u32 x;
 	__u32 i;
-	int ok;
 	yaffs_Device *dev;
 	yaffs_ExtendedTags tags;
 	yaffs_Tnode *tn;
@@ -829,7 +845,7 @@ static void yaffs_VerifyObjects(yaffs_De
 {
 	yaffs_Object *obj;
 	int i;
-	struct list_head *lh;
+	struct ylist_head *lh;
 
 	if(yaffs_SkipVerification(dev))
 		return;
@@ -837,9 +853,9 @@ static void yaffs_VerifyObjects(yaffs_De
 	/* Iterate through the objects in each hash entry */
 
 	 for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){
-	 	list_for_each(lh, &dev->objectBucket[i].list) {
+	 	ylist_for_each(lh, &dev->objectBucket[i].list) {
 			if (lh) {
-				obj = list_entry(lh, yaffs_Object, hashLink);
+				obj = ylist_entry(lh, yaffs_Object, hashLink);
 				yaffs_VerifyObject(obj);
 			}
 		}
@@ -1869,7 +1885,7 @@ static int yaffs_CreateFreeObjects(yaffs
 	/* Hook them into the free list */
 	for (i = 0; i < nObjects - 1; i++) {
 		newObjects[i].siblings.next =
-		    (struct list_head *)(&newObjects[i + 1]);
+		    (struct ylist_head *)(&newObjects[i + 1]);
 	}
 
 	newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
@@ -1909,9 +1925,9 @@ static yaffs_Object *yaffs_AllocateEmpty
 		tn->myDev = dev;
 		tn->chunkId = -1;
 		tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
-		INIT_LIST_HEAD(&(tn->hardLinks));
-		INIT_LIST_HEAD(&(tn->hashLink));
-		INIT_LIST_HEAD(&tn->siblings);
+		YINIT_LIST_HEAD(&(tn->hardLinks));
+		YINIT_LIST_HEAD(&(tn->hashLink));
+		YINIT_LIST_HEAD(&tn->siblings);
 
 		/* Add it to the lost and found directory.
 		 * NB Can't put root or lostNFound in lostNFound so
@@ -1954,8 +1970,8 @@ static void yaffs_UnhashObject(yaffs_Obj
 	yaffs_Device *dev = tn->myDev;
 
 	/* If it is still linked into the bucket list, free from the list */
-	if (!list_empty(&tn->hashLink)) {
-		list_del_init(&tn->hashLink);
+	if (!ylist_empty(&tn->hashLink)) {
+		ylist_del_init(&tn->hashLink);
 		bucket = yaffs_HashFunction(tn->objectId);
 		dev->objectBucket[bucket].count--;
 	}
@@ -1981,7 +1997,7 @@ static void yaffs_FreeObject(yaffs_Objec
 	yaffs_UnhashObject(tn);
 
 	/* Link into the free list. */
-	tn->siblings.next = (struct list_head *)(dev->freeObjects);
+	tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
 	dev->freeObjects = tn;
 	dev->nFreeObjects++;
 
@@ -2027,7 +2043,7 @@ static void yaffs_InitialiseObjects(yaff
 	dev->nFreeObjects = 0;
 
 	for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
-		INIT_LIST_HEAD(&dev->objectBucket[i].list);
+		YINIT_LIST_HEAD(&dev->objectBucket[i].list);
 		dev->objectBucket[i].count = 0;
 	}
 
@@ -2078,7 +2094,7 @@ static int yaffs_CreateNewObjectNumber(y
 	 */
 
 	int found = 0;
-	struct list_head *i;
+	struct ylist_head *i;
 
 	__u32 n = (__u32) bucket;
 
@@ -2088,10 +2104,10 @@ static int yaffs_CreateNewObjectNumber(y
 		found = 1;
 		n += YAFFS_NOBJECT_BUCKETS;
 		if (1 || dev->objectBucket[bucket].count > 0) {
-			list_for_each(i, &dev->objectBucket[bucket].list) {
+			ylist_for_each(i, &dev->objectBucket[bucket].list) {
 				/* If there is already one in the list */
 				if (i
-				    && list_entry(i, yaffs_Object,
+				    && ylist_entry(i, yaffs_Object,
 						  hashLink)->objectId == n) {
 					found = 0;
 				}
@@ -2108,7 +2124,7 @@ static void yaffs_HashObject(yaffs_Objec
 	int bucket = yaffs_HashFunction(in->objectId);
 	yaffs_Device *dev = in->myDev;
 
-	list_add(&in->hashLink, &dev->objectBucket[bucket].list);
+	ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
 	dev->objectBucket[bucket].count++;
 
 }
@@ -2116,13 +2132,13 @@ static void yaffs_HashObject(yaffs_Objec
 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
 {
 	int bucket = yaffs_HashFunction(number);
-	struct list_head *i;
+	struct ylist_head *i;
 	yaffs_Object *in;
 
-	list_for_each(i, &dev->objectBucket[bucket].list) {
+	ylist_for_each(i, &dev->objectBucket[bucket].list) {
 		/* Look if it is in the list */
 		if (i) {
-			in = list_entry(i, yaffs_Object, hashLink);
+			in = ylist_entry(i, yaffs_Object, hashLink);
 			if (in->objectId == number) {
 #ifdef __KERNEL__
 				/* Don't tell the VFS about this one if it is defered free */
@@ -2143,7 +2159,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
 {
 
 	yaffs_Object *theObject;
-	yaffs_Tnode *tn;
+	yaffs_Tnode *tn = NULL;
 
 	if (number < 0) {
 		number = yaffs_CreateNewObjectNumber(dev);
@@ -2191,7 +2207,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
 			theObject->variant.fileVariant.top = tn;
 			break;
 		case YAFFS_OBJECT_TYPE_DIRECTORY:
-			INIT_LIST_HEAD(&theObject->variant.directoryVariant.
+			YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
 				       children);
 			break;
 		case YAFFS_OBJECT_TYPE_SYMLINK:
@@ -2258,7 +2274,7 @@ static yaffs_Object *yaffs_MknodObject(y
 				       const YCHAR * aliasString, __u32 rdev)
 {
 	yaffs_Object *in;
-	YCHAR *str;
+	YCHAR *str = NULL;
 
 	yaffs_Device *dev = parent->myDev;
 
@@ -2316,7 +2332,7 @@ static yaffs_Object *yaffs_MknodObject(y
 			    equivalentObject;
 			in->variant.hardLinkVariant.equivalentObjectId =
 			    equivalentObject->objectId;
-			list_add(&in->hardLinks, &equivalentObject->hardLinks);
+			ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
 			break;
 		case YAFFS_OBJECT_TYPE_FILE:
 		case YAFFS_OBJECT_TYPE_DIRECTORY:
@@ -2477,7 +2493,7 @@ int yaffs_RenameObject(yaffs_Object * ol
 		existingTarget = yaffs_FindObjectByName(newDir, newName);
 		if (existingTarget &&
 		    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
-		    !list_empty(&existingTarget->variant.directoryVariant.children)) {
+		    !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
 			/* There is a target that is a non-empty directory, so we fail */
 			return YAFFS_FAIL;	/* EEXIST or ENOTEMPTY */
 		} else if (existingTarget && existingTarget != obj) {
@@ -3091,7 +3107,7 @@ static int yaffs_GarbageCollectBlock(yaf
 						yaffs_ObjectHeader *oh;
 						oh = (yaffs_ObjectHeader *)buffer;
 						oh->isShrink = 0;
-						oh->shadowsObject = -1;
+						oh->shadowsObject = oh->inbandShadowsObject = -1;
 						tags.extraShadows = 0;
 						tags.extraIsShrinkHeader = 0;
 
@@ -3682,7 +3698,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
 
 		oh->type = in->variantType;
 		oh->yst_mode = in->yst_mode;
-		oh->shadowsObject = shadows;
+		oh->shadowsObject = oh->inbandShadowsObject = shadows;
 
 #ifdef CONFIG_YAFFS_WINCE
 		oh->win_atime[0] = in->win_atime[0];
@@ -4376,7 +4392,7 @@ static int yaffs_WriteCheckpointObjects(
 	yaffs_CheckpointObject cp;
 	int i;
 	int ok = 1;
-	struct list_head *lh;
+	struct ylist_head *lh;
 
 
 	/* Iterate through the objects in each hash entry,
@@ -4384,9 +4400,9 @@ static int yaffs_WriteCheckpointObjects(
 	 */
 
 	 for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
-	 	list_for_each(lh, &dev->objectBucket[i].list) {
+	 	ylist_for_each(lh, &dev->objectBucket[i].list) {
 			if (lh) {
-				obj = list_entry(lh, yaffs_Object, hashLink);
+				obj = ylist_entry(lh, yaffs_Object, hashLink);
 				if (!obj->deferedFree) {
 					yaffs_ObjectToCheckpointObject(&cp,obj);
 					cp.structType = sizeof(cp);
@@ -4444,7 +4460,7 @@ static int yaffs_ReadCheckpointObjects(y
 					ok = yaffs_ReadCheckpointTnodes(obj);
 				} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
 					obj->hardLinks.next =
-						    (struct list_head *)
+						    (struct ylist_head *)
 						    hardList;
 					hardList = obj;
 				}
@@ -4650,7 +4666,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
 {
 
 	int chunk;
-	int start;
+	__u32 start;
 	int nToCopy;
 	int n = nBytes;
 	int nDone = 0;
@@ -4678,10 +4694,10 @@ int yaffs_ReadDataFromFile(yaffs_Object 
 		cache = yaffs_FindChunkCache(in, chunk);
 
 		/* If the chunk is already in the cache or it is less than a whole chunk
-		 * then use the cache (if there is caching)
+		 * or we're using inband tags then use the cache (if there is caching)
 		 * else bypass the cache.
 		 */
-		if (cache || nToCopy != dev->nDataBytesPerChunk) {
+		if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
 			if (dev->nShortOpCaches > 0) {
 
 				/* If we can't find the data in the cache, then load it up. */
@@ -4770,7 +4786,7 @@ int yaffs_WriteDataToFile(yaffs_Object *
 {
 
 	int chunk;
-	int start;
+	__u32 start;
 	int nToCopy;
 	int n = nBytes;
 	int nDone = 0;
@@ -4818,8 +4834,10 @@ int yaffs_WriteDataToFile(yaffs_Object *
 			nToWriteBack = dev->nDataBytesPerChunk;
 		}
 
-		if (nToCopy != dev->nDataBytesPerChunk) {
-			/* An incomplete start or end chunk (or maybe both start and end chunk) */
+		if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
+			/* An incomplete start or end chunk (or maybe both start and end chunk), 
+			 * or we're using inband tags, so we want to use the cache buffers.
+			 */
 			if (dev->nShortOpCaches > 0) {
 				yaffs_ChunkCache *cache;
 				/* If we can't find the data in the cache, then load the cache */
@@ -4907,7 +4925,8 @@ int yaffs_WriteDataToFile(yaffs_Object *
 			}
 
 		} else {
-
+			/* A full chunk. Write directly from the supplied buffer. */
+			
 #ifdef CONFIG_YAFFS_WINCE
 			/* Under WinCE can't do direct transfer. Need to use a local buffer.
 			 * This is because we otherwise screw up WinCE's memory mapper
@@ -4926,7 +4945,7 @@ int yaffs_WriteDataToFile(yaffs_Object *
 							 0);
 			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
 #else
-			/* A full chunk. Write directly from the supplied buffer. */
+
 			chunkWritten =
 			    yaffs_WriteChunkDataToObject(in, chunk, buffer,
 							 dev->nDataBytesPerChunk,
@@ -5004,7 +5023,7 @@ int yaffs_ResizeFile(yaffs_Object * in, 
 {
 
 	int oldFileSize = in->variant.fileVariant.fileSize;
-	int newSizeOfPartialChunk;
+	__u32 newSizeOfPartialChunk;
 	int newFullChunks;
 
 	yaffs_Device *dev = in->myDev;
@@ -5017,11 +5036,11 @@ int yaffs_ResizeFile(yaffs_Object * in, 
 	yaffs_CheckGarbageCollection(dev);
 
 	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
-		return yaffs_GetFileSize(in);
+		return YAFFS_FAIL;
 	}
 
 	if (newSize == oldFileSize) {
-		return oldFileSize;
+		return YAFFS_OK;
 	}
 
 	if (newSize < oldFileSize) {
@@ -5119,7 +5138,7 @@ static int yaffs_DoGenericObjectDeletion
 
 	if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
 		/* Move to the unlinked directory so we have a record that it was deleted. */
-		yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
+		yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
 
 	}
 
@@ -5157,7 +5176,7 @@ static int yaffs_UnlinkFile(yaffs_Object
 		if (immediateDeletion) {
 			retVal =
 			    yaffs_ChangeObjectName(in, in->myDev->deletedDir,
-						   "deleted", 0, 0);
+						   _Y("deleted"), 0, 0);
 			T(YAFFS_TRACE_TRACING,
 			  (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
 			   in->objectId));
@@ -5170,7 +5189,7 @@ static int yaffs_UnlinkFile(yaffs_Object
 		} else {
 			retVal =
 			    yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
-						   "unlinked", 0, 0);
+						   _Y("unlinked"), 0, 0);
 		}
 
 	}
@@ -5205,7 +5224,7 @@ int yaffs_DeleteFile(yaffs_Object * in)
 static int yaffs_DeleteDirectory(yaffs_Object * in)
 {
 	/* First check that the directory is empty. */
-	if (list_empty(&in->variant.directoryVariant.children)) {
+	if (ylist_empty(&in->variant.directoryVariant.children)) {
 		return yaffs_DoGenericObjectDeletion(in);
 	}
 
@@ -5225,7 +5244,7 @@ static int yaffs_DeleteHardLink(yaffs_Ob
 	/* remove this hardlink from the list assocaited with the equivalent
 	 * object
 	 */
-	list_del(&in->hardLinks);
+	ylist_del(&in->hardLinks);
 	return yaffs_DoGenericObjectDeletion(in);
 }
 
@@ -5257,7 +5276,7 @@ static int yaffs_UnlinkWorker(yaffs_Obje
 
 	if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
 		return yaffs_DeleteHardLink(obj);
-	} else if (!list_empty(&obj->hardLinks)) {
+	} else if (!ylist_empty(&obj->hardLinks)) {
 		/* Curve ball: We're unlinking an object that has a hardlink.
 		 *
 		 * This problem arises because we are not strictly following
@@ -5276,10 +5295,10 @@ static int yaffs_UnlinkWorker(yaffs_Obje
 		int retVal;
 		YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
 
-		hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
-
-		list_del_init(&hl->hardLinks);
-		list_del_init(&hl->siblings);
+		hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
+
+		ylist_del_init(&hl->hardLinks);
+		ylist_del_init(&hl->siblings);
 
 		yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
 
@@ -5386,13 +5405,13 @@ static void yaffs_HardlinkFixup(yaffs_De
 		if (in) {
 			/* Add the hardlink pointers */
 			hl->variant.hardLinkVariant.equivalentObject = in;
-			list_add(&hl->hardLinks, &in->hardLinks);
+			ylist_add(&hl->hardLinks, &in->hardLinks);
 		} else {
 			/* Todo Need to report/handle this better.
 			 * Got a problem... hardlink to a non-existant object
 			 */
 			hl->variant.hardLinkVariant.equivalentObject = NULL;
-			INIT_LIST_HEAD(&hl->hardLinks);
+			YINIT_LIST_HEAD(&hl->hardLinks);
 
 		}
 
@@ -5432,7 +5451,7 @@ static int yaffs_Scan(yaffs_Device * dev
 	yaffs_BlockState state;
 	yaffs_Object *hardList = NULL;
 	yaffs_BlockInfo *bi;
-	int sequenceNumber;
+	__u32 sequenceNumber;
 	yaffs_ObjectHeader *oh;
 	yaffs_Object *in;
 	yaffs_Object *parent;
@@ -5609,8 +5628,7 @@ static int yaffs_Scan(yaffs_Device * dev
 						bi->sequenceNumber)) {
 						T(YAFFS_TRACE_ALWAYS,
 						  (TSTR
-						   ("yaffs: Allocation block %d was not highest sequence id:"
-						    " block seq = %d, dev seq = %d"
+						   ("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d"
 						    TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
 					}
 				}
@@ -5784,7 +5802,7 @@ static int yaffs_Scan(yaffs_Device * dev
 						/* Set up as a directory */
 						parent->variantType =
 						    YAFFS_OBJECT_TYPE_DIRECTORY;
-						INIT_LIST_HEAD(&parent->variant.
+						YINIT_LIST_HEAD(&parent->variant.
 							       directoryVariant.
 							       children);
 					} else if (parent->variantType !=
@@ -5796,8 +5814,7 @@ static int yaffs_Scan(yaffs_Device * dev
 
 						T(YAFFS_TRACE_ERROR,
 						  (TSTR
-						   ("yaffs tragedy: attempting to use non-directory as"
-						    " a directory in scan. Put in lost+found."
+						   ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
 						    TENDSTR)));
 						parent = dev->lostNFoundDir;
 					}
@@ -5842,7 +5859,7 @@ static int yaffs_Scan(yaffs_Device * dev
 						    equivalentObjectId =
 						    oh->equivalentObjectId;
 						in->hardLinks.next =
-						    (struct list_head *)
+						    (struct ylist_head *)
 						    hardList;
 						hardList = in;
 						break;
@@ -5901,16 +5918,16 @@ static int yaffs_Scan(yaffs_Device * dev
 	 * just delete them.
 	 */
 	{
-		struct list_head *i;
-		struct list_head *n;
+		struct ylist_head *i;
+		struct ylist_head *n;
 
 		yaffs_Object *l;
 		/* Soft delete all the unlinked files */
-		list_for_each_safe(i, n,
+		ylist_for_each_safe(i, n,
 				   &dev->unlinkedDir->variant.directoryVariant.
 				   children) {
 			if (i) {
-				l = list_entry(i, yaffs_Object, siblings);
+				l = ylist_entry(i, yaffs_Object, siblings);
 				yaffs_DestroyObject(l);
 			}
 		}
@@ -5999,7 +6016,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
 	yaffs_BlockState state;
 	yaffs_Object *hardList = NULL;
 	yaffs_BlockInfo *bi;
-	int sequenceNumber;
+	__u32 sequenceNumber;
 	yaffs_ObjectHeader *oh;
 	yaffs_Object *in;
 	yaffs_Object *parent;
@@ -6328,6 +6345,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
 									NULL);
 
 					oh = (yaffs_ObjectHeader *) chunkData;
+					
+					if(dev->inbandTags){
+						/* Fix up the header if they got corrupted by inband tags */
+						oh->shadowsObject = oh->inbandShadowsObject;
+						oh->isShrink = oh->inbandIsShrink;
+					}
 
 					if (!in)
 						in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
@@ -6338,8 +6361,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
 					/* TODO Hoosterman we have a problem! */
 					T(YAFFS_TRACE_ERROR,
 					  (TSTR
-					   ("yaffs tragedy: Could not make object for object  %d  "
-					    "at chunk %d during scan"
+					   ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
 					    TENDSTR), tags.objectId, chunk));
 
 				}
@@ -6497,7 +6519,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
 						/* Set up as a directory */
 						parent->variantType =
 						    YAFFS_OBJECT_TYPE_DIRECTORY;
-						INIT_LIST_HEAD(&parent->variant.
+						YINIT_LIST_HEAD(&parent->variant.
 							       directoryVariant.
 							       children);
 					} else if (parent->variantType !=
@@ -6509,8 +6531,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
 
 						T(YAFFS_TRACE_ERROR,
 						  (TSTR
-						   ("yaffs tragedy: attempting to use non-directory as"
-						    " a directory in scan. Put in lost+found."
+						   ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
 						    TENDSTR)));
 						parent = dev->lostNFoundDir;
 					}
@@ -6561,7 +6582,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
 						  in->variant.hardLinkVariant.equivalentObjectId =
 						    equivalentObjectId;
 						  in->hardLinks.next =
-						    (struct list_head *) hardList;
+						    (struct ylist_head *) hardList;
 						  hardList = in;
 						}
 						break;
@@ -6621,27 +6642,27 @@ static int yaffs_ScanBackwards(yaffs_Dev
 	*  Sort out state of unlinked and deleted objects.
 	*/
 	{
-		struct list_head *i;
-		struct list_head *n;
+		struct ylist_head *i;
+		struct ylist_head *n;
 
 		yaffs_Object *l;
 
 		/* Soft delete all the unlinked files */
-		list_for_each_safe(i, n,
+		ylist_for_each_safe(i, n,
 				   &dev->unlinkedDir->variant.directoryVariant.
 				   children) {
 			if (i) {
-				l = list_entry(i, yaffs_Object, siblings);
+				l = ylist_entry(i, yaffs_Object, siblings);
 				yaffs_DestroyObject(l);
 			}
 		}
 
 		/* Soft delete all the deletedDir files */
-		list_for_each_safe(i, n,
+		ylist_for_each_safe(i, n,
 				   &dev->deletedDir->variant.directoryVariant.
 				   children) {
 			if (i) {
-				l = list_entry(i, yaffs_Object, siblings);
+				l = ylist_entry(i, yaffs_Object, siblings);
 				yaffs_DestroyObject(l);
 
 			}
@@ -6668,7 +6689,7 @@ static void yaffs_RemoveObjectFromDirect
 	if(dev && dev->removeObjectCallback)
 		dev->removeObjectCallback(obj);
 
-	list_del_init(&obj->siblings);
+	ylist_del_init(&obj->siblings);
 	obj->parent = NULL;
 }
 
@@ -6694,14 +6715,14 @@ static void yaffs_AddObjectToDirectory(y
 
 	if (obj->siblings.prev == NULL) {
 		/* Not initialised */
-		INIT_LIST_HEAD(&obj->siblings);
-
-	} else if (!list_empty(&obj->siblings)) {
+		YINIT_LIST_HEAD(&obj->siblings);
+
+	} else if (!ylist_empty(&obj->siblings)) {
 		/* If it is holed up somewhere else, un hook it */
 		yaffs_RemoveObjectFromDirectory(obj);
 	}
 	/* Now add it */
-	list_add(&obj->siblings, &directory->variant.directoryVariant.children);
+	ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
 	obj->parent = directory;
 
 	if (directory == obj->myDev->unlinkedDir
@@ -6717,7 +6738,7 @@ yaffs_Object *yaffs_FindObjectByName(yaf
 {
 	int sum;
 
-	struct list_head *i;
+	struct ylist_head *i;
 	YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
 
 	yaffs_Object *l;
@@ -6742,9 +6763,9 @@ yaffs_Object *yaffs_FindObjectByName(yaf
 
 	sum = yaffs_CalcNameSum(name);
 
-	list_for_each(i, &directory->variant.directoryVariant.children) {
+	ylist_for_each(i, &directory->variant.directoryVariant.children) {
 		if (i) {
-			l = list_entry(i, yaffs_Object, siblings);
+			l = ylist_entry(i, yaffs_Object, siblings);
 
 			yaffs_CheckObjectDetailsLoaded(l);
 
@@ -6776,7 +6797,7 @@ yaffs_Object *yaffs_FindObjectByName(yaf
 int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
 				   int (*fn) (yaffs_Object *))
 {
-	struct list_head *i;
+	struct ylist_head *i;
 	yaffs_Object *l;
 
 	if (!theDir) {
@@ -6793,9 +6814,9 @@ int yaffs_ApplyToDirectoryChildren(yaffs
 		YBUG();
 	}
 
-	list_for_each(i, &theDir->variant.directoryVariant.children) {
+	ylist_for_each(i, &theDir->variant.directoryVariant.children) {
 		if (i) {
-			l = list_entry(i, yaffs_Object, siblings);
+			l = ylist_entry(i, yaffs_Object, siblings);
 			if (l && !fn(l)) {
 				return YAFFS_FAIL;
 			}
@@ -6884,12 +6905,12 @@ int yaffs_GetObjectFileLength(yaffs_Obje
 int yaffs_GetObjectLinkCount(yaffs_Object * obj)
 {
 	int count = 0;
-	struct list_head *i;
+	struct ylist_head *i;
 
 	if (!obj->unlinked) {
 		count++;	/* the object itself */
 	}
-	list_for_each(i, &obj->hardLinks) {
+	ylist_for_each(i, &obj->hardLinks) {
 		count++;	/* add the hard links; */
 	}
 	return count;
@@ -7112,8 +7133,9 @@ int yaffs_GutsInitialise(yaffs_Device * 
 
 	/* Check geometry parameters. */
 
-	if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
-	    (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
+	if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) ||
+	    (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) ||
+	    (dev->inbandTags && !dev->isYaffs2 ) ||
 	     dev->nChunksPerBlock < 2 ||
 	     dev->nReservedBlocks < 2 ||
 	     dev->internalStartBlock <= 0 ||
@@ -7122,8 +7144,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
 	    ) {
 		T(YAFFS_TRACE_ALWAYS,
 		  (TSTR
-		   ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
-		    TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
+		   ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
+		    TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
 		return YAFFS_FAIL;
 	}
 
@@ -7132,6 +7154,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
 		  (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
 		return YAFFS_FAIL;
 	}
+	
+	/* Sort out space for inband tags, if required */
+	if(dev->inbandTags)
+		dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
+	else 
+		dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
 
 	/* Got the right mix of functions? */
 	if (!yaffs_CheckDevFunctions(dev)) {
@@ -7167,22 +7195,14 @@ int yaffs_GutsInitialise(yaffs_Device * 
 	/*
 	 *  Calculate all the chunk size manipulation numbers:
 	 */
-	 /* Start off assuming it is a power of 2 */
-	 dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
-	 dev->chunkMask = (1<<dev->chunkShift) - 1;
-
-	 if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
-	 	/* Yes it is a power of 2, disable crumbs */
-		dev->crumbMask = 0;
-		dev->crumbShift = 0;
-		dev->crumbsPerChunk = 0;
-	 } else {
-	 	/* Not a power of 2, use crumbs instead */
-		dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
-		dev->crumbMask = (1<<dev->crumbShift)-1;
-		dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
-		dev->chunkShift = 0;
-		dev->chunkMask = 0;
+ 	 {
+		__u32 x = dev->nDataBytesPerChunk;
+		 /* We always use dev->chunkShift and dev->chunkDiv */
+		 dev->chunkShift = Shifts(x);
+		 x >>= dev->chunkShift;
+		 dev->chunkDiv = x;
+		 /* We only use chunk mask if chunkDiv is 1 */
+		 dev->chunkMask = (1<<dev->chunkShift) - 1;
 	}
 
 
@@ -7266,7 +7286,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
 	if (!init_failed &&
 	    dev->nShortOpCaches > 0) {
 		int i;
-		__u8 *buf;
+		void *buf;
 		int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
 
 		if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
@@ -7282,7 +7302,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
 			dev->srCache[i].object = NULL;
 			dev->srCache[i].lastUse = 0;
 			dev->srCache[i].dirty = 0;
-			dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
+			dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
 		}
 		if(!buf)
 			init_failed = 1;
@@ -7408,6 +7428,7 @@ void yaffs_Deinitialise(yaffs_Device * d
 			YFREE(dev->tempBuffer[i].buffer);
 		}
 
+
 		dev->isMounted = 0;
 	}
 
@@ -7511,22 +7532,25 @@ static void yaffs_VerifyFreeChunks(yaffs
 /*---------------------------------------- YAFFS test code ----------------------*/
 
 #define yaffs_CheckStruct(structure,syze, name) \
+	do { \
            if(sizeof(structure) != syze) \
 	       { \
 	         T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
 		 name,syze,sizeof(structure))); \
 	         return YAFFS_FAIL; \
-		}
+		} \
+	} while(0)
 
 static int yaffs_CheckStructures(void)
 {
-/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
-/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
-/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
+/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
+/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
+/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
 #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
-	yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
+	yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
 #endif
-	    yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
-
+#ifndef CONFIG_YAFFS_WINCE
+		yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
+#endif
 	    return YAFFS_OK;
 }
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -90,7 +90,7 @@
 
 #define YAFFS_MAX_SHORT_OP_CACHES	20
 
-#define YAFFS_N_TEMP_BUFFERS		4
+#define YAFFS_N_TEMP_BUFFERS		6
 
 /* We limit the number attempts at sucessfully saving a chunk of data.
  * Small-page devices have 32 pages per block; large-page devices have 64.
@@ -331,11 +331,14 @@ typedef struct {
 	__u32 win_ctime[2];
 	__u32 win_atime[2];
 	__u32 win_mtime[2];
-	__u32 roomToGrow[4];
 #else
-	__u32 roomToGrow[10];
+	__u32 roomToGrow[6];
+
 #endif
+	__u32 inbandShadowsObject;
+	__u32 inbandIsShrink;
 
+	__u32 reservedSpace[2];
 	int shadowsObject;	/* This object header shadows the specified object if > 0 */
 
 	/* isShrink applies to object headers written when we shrink the file (ie resize) */
@@ -381,7 +384,7 @@ typedef struct {
 } yaffs_FileStructure;
 
 typedef struct {
-	struct list_head children;	/* list of child links */
+	struct ylist_head children;	/* list of child links */
 } yaffs_DirectoryStructure;
 
 typedef struct {
@@ -424,14 +427,14 @@ struct yaffs_ObjectStruct {
 
 	struct yaffs_DeviceStruct *myDev;	/* The device I'm on */
 
-	struct list_head hashLink;	/* list of objects in this hash bucket */
+	struct ylist_head hashLink;	/* list of objects in this hash bucket */
 
-	struct list_head hardLinks;	/* all the equivalent hard linked objects */
+	struct ylist_head hardLinks;	/* all the equivalent hard linked objects */
 
 	/* directory structure stuff */
 	/* also used for linking up the free list */
 	struct yaffs_ObjectStruct *parent;
-	struct list_head siblings;
+	struct ylist_head siblings;
 
 	/* Where's my object header in NAND? */
 	int chunkId;
@@ -485,7 +488,7 @@ struct yaffs_ObjectList_struct {
 typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
 
 typedef struct {
-	struct list_head list;
+	struct ylist_head list;
 	int count;
 } yaffs_ObjectBucket;
 
@@ -528,7 +531,7 @@ typedef struct {
 /*----------------- Device ---------------------------------*/
 
 struct yaffs_DeviceStruct {
-	struct list_head devList;
+	struct ylist_head devList;
 	const char *name;
 
 	/* Entry parameters set up way early. Yaffs sets up the rest.*/
@@ -583,7 +586,7 @@ struct yaffs_DeviceStruct {
 					  yaffs_ExtendedTags * tags);
 	int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
 	int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
-			       yaffs_BlockState * state, int *sequenceNumber);
+			       yaffs_BlockState * state, __u32 *sequenceNumber);
 #endif
 
 	int isYaffs2;
@@ -598,7 +601,8 @@ struct yaffs_DeviceStruct {
 	void (*markSuperBlockDirty)(void * superblock);
 
 	int wideTnodesDisabled; /* Set to disable wide tnodes */
-
+	
+	YCHAR *pathDividers;	/* String of legal path dividers */
 
 	/* End of stuff that must be set before initialisation. */
 
@@ -615,16 +619,14 @@ struct yaffs_DeviceStruct {
 	__u32 tnodeWidth;
 	__u32 tnodeMask;
 
-	/* Stuff to support various file offses to chunk/offset translations */
-	/* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
-	__u32 crumbMask;
-	__u32 crumbShift;
-	__u32 crumbsPerChunk;
+	/* Stuff for figuring out file offset to chunk conversions */
+	__u32 chunkShift; /* Shift value */
+	__u32 chunkDiv;   /* Divisor after shifting: 1 for power-of-2 sizes */
+	__u32 chunkMask;  /* Mask to use for power-of-2 case */
 
-	/* Straight shifting for nDataBytesPerChunk being a power of 2 */
-	__u32 chunkShift;
-	__u32 chunkMask;
-
+	/* Stuff to handle inband tags */
+	int inbandTags;
+	__u32 totalBytesPerChunk;
 
 #ifdef __KERNEL__
 
@@ -746,9 +748,11 @@ struct yaffs_DeviceStruct {
 	int nUnlinkedFiles;		/* Count of unlinked files. */
 	int nBackgroundDeletions;	/* Count of background deletions. */
 
-
+	
+	/* Temporary buffer management */
 	yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
 	int maxTemp;
+	int tempInUse;
 	int unmanagedTempAllocations;
 	int unmanagedTempDeallocations;
 
@@ -799,18 +803,6 @@ typedef struct {
     __u32 head;
 } yaffs_CheckpointValidity;
 
-/* Function to manipulate block info */
-static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
-{
-	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
-		T(YAFFS_TRACE_ERROR,
-		  (TSTR
-		   ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
-		   blk));
-		YBUG();
-	}
-	return &dev->blockInfo[blk - dev->internalStartBlock];
-}
 
 /*----------------------- YAFFS Functions -----------------------*/
 
@@ -901,4 +893,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
 int yaffs_CheckFF(__u8 * buffer, int nBytes);
 void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
 
+__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
+void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
+
 #endif
--- a/yaffs_mtdif2.c
+++ b/yaffs_mtdif2.c
@@ -27,6 +27,10 @@ const char *yaffs_mtdif2_c_version =
 
 #include "yaffs_packedtags2.h"
 
+/* NB For use with inband tags....
+ * We assume that the data buffer is of size totalBytersPerChunk so that we can also
+ * use it to load the tags.
+ */
 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
 				      const __u8 * data,
 				      const yaffs_ExtendedTags * tags)
@@ -39,7 +43,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
 #endif
 	int retval = 0;
 
-	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+	loff_t addr;
 
 	yaffs_PackedTags2 pt;
 
@@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
 	  (TSTR
 	   ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
 	    TENDSTR), chunkInNAND, data, tags));
-
-#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
-	if (tags)
-		yaffs_PackTags2(&pt, tags);
-	else
-		BUG(); /* both tags and data should always be present */
+	    
 
-	if (data) {
-		ops.mode = MTD_OOB_AUTO;
-		ops.ooblen = sizeof(pt);
-		ops.len = dev->nDataBytesPerChunk;
-		ops.ooboffs = 0;
-		ops.datbuf = (__u8 *)data;
-		ops.oobbuf = (void *)&pt;
-		retval = mtd->write_oob(mtd, addr, &ops);
-	} else
-		BUG(); /* both tags and data should always be present */
-#else
-	if (tags) {
-		yaffs_PackTags2(&pt, tags);
+	addr  = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
+	
+	/* For yaffs2 writing there must be both data and tags.
+	 * If we're using inband tags, then the tags are stuffed into
+	 * the end of the data buffer.
+	 */
+	if(!data || !tags)
+		BUG();	
+	else if(dev->inbandTags){
+		yaffs_PackedTags2TagsPart *pt2tp;
+		pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
+		yaffs_PackTags2TagsPart(pt2tp,tags);
 	}
+	else
+		yaffs_PackTags2(&pt, tags);
+	
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+	ops.mode = MTD_OOB_AUTO;
+	ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
+	ops.len = dev->totalBytesPerChunk;
+	ops.ooboffs = 0;
+	ops.datbuf = (__u8 *)data;
+	ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
+	retval = mtd->write_oob(mtd, addr, &ops);
 
-	if (data && tags) {
-		if (dev->useNANDECC)
-			retval =
-			    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
-					   &dummy, data, (__u8 *) & pt, NULL);
-		else
-			retval =
-			    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
-					   &dummy, data, (__u8 *) & pt, NULL);
+#else
+	if (!dev->inbandTags) {
+		retval =
+		    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+				   &dummy, data, (__u8 *) & pt, NULL);
 	} else {
-		if (data)
-			retval =
-			    mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
-				       data);
-		if (tags)
-			retval =
-			    mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
-					   (__u8 *) & pt);
-
+		retval =
+		    mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
+			       data);
 	}
 #endif
 
@@ -106,6 +105,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 #endif
 	size_t dummy;
 	int retval = 0;
+	int localData = 0;
 
 	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
 
@@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 	  (TSTR
 	   ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
 	    TENDSTR), chunkInNAND, data, tags));
+	    
+	if(dev->inbandTags){
+		
+		if(!data) {
+			localData = 1;
+			data = yaffs_GetTempBuffer(dev,__LINE__);
+		}
+		
 
-#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
-	if (data && !tags)
-		retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
+	}
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+	if (dev->inbandTags || (data && !tags))
+		retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
 				&dummy, data);
 	else if (tags) {
 		ops.mode = MTD_OOB_AUTO;
@@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 		retval = mtd->read_oob(mtd, addr, &ops);
 	}
 #else
-	if (data && tags) {
-		if (dev->useNANDECC) {
-			retval =
-			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+	if (!dev->inbandTags && data && tags) {
+
+		retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
 					  &dummy, data, dev->spareBuffer,
 					  NULL);
-		} else {
-			retval =
-			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
-					  &dummy, data, dev->spareBuffer,
-					  NULL);
-		}
 	} else {
 		if (data)
 			retval =
 			    mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
 				      data);
-		if (tags)
+		if (!dev->inbandTags && tags)
 			retval =
 			    mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
 					  dev->spareBuffer);
 	}
 #endif
 
-	memcpy(&pt, dev->spareBuffer, sizeof(pt));
 
-	if (tags)
-		yaffs_UnpackTags2(tags, &pt);
+	if(dev->inbandTags){
+		if(tags){
+			yaffs_PackedTags2TagsPart * pt2tp;
+			pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];	
+			yaffs_UnpackTags2TagsPart(tags,pt2tp);
+		}
+	}
+	else {
+		if (tags){
+			memcpy(&pt, dev->spareBuffer, sizeof(pt));
+			yaffs_UnpackTags2(tags, &pt);
+		}
+	}
 
+	if(localData)
+		yaffs_ReleaseTempBuffer(dev,data,__LINE__);
+	
 	if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
-		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
-
+		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;		
 	if (retval == 0)
 		return YAFFS_OK;
 	else
--- a/yaffs_nand.c
+++ b/yaffs_nand.c
@@ -18,6 +18,7 @@ const char *yaffs_nand_c_version =
 #include "yaffs_tagscompat.h"
 #include "yaffs_tagsvalidity.h"
 
+#include "yaffs_getblockinfo.h"
 
 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
 					   __u8 * buffer,
@@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
 int yaffs_QueryInitialBlockState(yaffs_Device * dev,
 						 int blockNo,
 						 yaffs_BlockState * state,
-						 unsigned *sequenceNumber)
+						 __u32 *sequenceNumber)
 {
 	blockNo -= dev->blockOffset;
 
--- a/yaffs_nandemul2k.h
+++ b/yaffs_nandemul2k.h
@@ -22,13 +22,13 @@
 
 int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
 					int chunkInNAND, const __u8 * data,
-					yaffs_ExtendedTags * tags);
+					const yaffs_ExtendedTags * tags);
 int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
 					 int chunkInNAND, __u8 * data,
 					 yaffs_ExtendedTags * tags);
 int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
 int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
-			      yaffs_BlockState * state, int *sequenceNumber);
+			      yaffs_BlockState * state, __u32 *sequenceNumber);
 int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
 				int blockInNAND);
 int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
--- a/yaffs_packedtags2.c
+++ b/yaffs_packedtags2.c
@@ -37,60 +37,70 @@
 #define EXTRA_OBJECT_TYPE_SHIFT (28)
 #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
 
-static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
+
+static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
 {
 	T(YAFFS_TRACE_MTD,
 	  (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
-	   pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
-	   pt->t.sequenceNumber));
+	   ptt->objectId, ptt->chunkId, ptt->byteCount,
+	   ptt->sequenceNumber));
+}
+static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
+{
+	yaffs_DumpPackedTags2TagsPart(&pt->t);
 }
 
 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
 {
 	T(YAFFS_TRACE_MTD,
 	  (TSTR
-	   ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
-	    "%d del %d ser %d seq %d"
+	   ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
 	    TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
 	   t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
 	   t->sequenceNumber));
 
 }
 
-void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
 {
-	pt->t.chunkId = t->chunkId;
-	pt->t.sequenceNumber = t->sequenceNumber;
-	pt->t.byteCount = t->byteCount;
-	pt->t.objectId = t->objectId;
+	ptt->chunkId = t->chunkId;
+	ptt->sequenceNumber = t->sequenceNumber;
+	ptt->byteCount = t->byteCount;
+	ptt->objectId = t->objectId;
 
 	if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
 		/* Store the extra header info instead */
 		/* We save the parent object in the chunkId */
-		pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
+		ptt->chunkId = EXTRA_HEADER_INFO_FLAG
 			| t->extraParentObjectId;
 		if (t->extraIsShrinkHeader) {
-			pt->t.chunkId |= EXTRA_SHRINK_FLAG;
+			ptt->chunkId |= EXTRA_SHRINK_FLAG;
 		}
 		if (t->extraShadows) {
-			pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
+			ptt->chunkId |= EXTRA_SHADOWS_FLAG;
 		}
 
-		pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
-		pt->t.objectId |=
+		ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+		ptt->objectId |=
 		    (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
 
 		if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
-			pt->t.byteCount = t->extraEquivalentObjectId;
+			ptt->byteCount = t->extraEquivalentObjectId;
 		} else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
-			pt->t.byteCount = t->extraFileLength;
+			ptt->byteCount = t->extraFileLength;
 		} else {
-			pt->t.byteCount = 0;
+			ptt->byteCount = 0;
 		}
 	}
 
-	yaffs_DumpPackedTags2(pt);
+	yaffs_DumpPackedTags2TagsPart(ptt);
 	yaffs_DumpTags2(t);
+}
+
+
+void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
+{
+	yaffs_PackTags2TagsPart(&pt->t,t);
 
 #ifndef YAFFS_IGNORE_TAGS_ECC
 	{
@@ -101,13 +111,60 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
 #endif
 }
 
-void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
+
+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
 {
 
 	memset(t, 0, sizeof(yaffs_ExtendedTags));
 
 	yaffs_InitialiseTags(t);
 
+	if (ptt->sequenceNumber != 0xFFFFFFFF) {
+		t->blockBad = 0;
+		t->chunkUsed = 1;
+		t->objectId = ptt->objectId;
+		t->chunkId = ptt->chunkId;
+		t->byteCount = ptt->byteCount;
+		t->chunkDeleted = 0;
+		t->serialNumber = 0;
+		t->sequenceNumber = ptt->sequenceNumber;
+
+		/* Do extra header info stuff */
+
+		if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
+			t->chunkId = 0;
+			t->byteCount = 0;
+
+			t->extraHeaderInfoAvailable = 1;
+			t->extraParentObjectId =
+			    ptt->chunkId & (~(ALL_EXTRA_FLAGS));
+			t->extraIsShrinkHeader =
+			    (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
+			t->extraShadows =
+			    (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
+			t->extraObjectType =
+			    ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
+			t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+
+			if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+				t->extraEquivalentObjectId = ptt->byteCount;
+			} else {
+				t->extraFileLength = ptt->byteCount;
+			}
+		}
+	}
+
+	yaffs_DumpPackedTags2TagsPart(ptt);
+	yaffs_DumpTags2(t);
+
+}
+
+
+void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
+{
+
+	yaffs_UnpackTags2TagsPart(t,&pt->t);
+
 	if (pt->t.sequenceNumber != 0xFFFFFFFF) {
 		/* Page is in use */
 #ifdef YAFFS_IGNORE_TAGS_ECC
@@ -142,41 +199,10 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
 			}
 		}
 #endif
-		t->blockBad = 0;
-		t->chunkUsed = 1;
-		t->objectId = pt->t.objectId;
-		t->chunkId = pt->t.chunkId;
-		t->byteCount = pt->t.byteCount;
-		t->chunkDeleted = 0;
-		t->serialNumber = 0;
-		t->sequenceNumber = pt->t.sequenceNumber;
-
-		/* Do extra header info stuff */
-
-		if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
-			t->chunkId = 0;
-			t->byteCount = 0;
-
-			t->extraHeaderInfoAvailable = 1;
-			t->extraParentObjectId =
-			    pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
-			t->extraIsShrinkHeader =
-			    (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
-			t->extraShadows =
-			    (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
-			t->extraObjectType =
-			    pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
-			t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
-
-			if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
-				t->extraEquivalentObjectId = pt->t.byteCount;
-			} else {
-				t->extraFileLength = pt->t.byteCount;
-			}
-		}
 	}
 
 	yaffs_DumpPackedTags2(pt);
 	yaffs_DumpTags2(t);
 
 }
+
--- a/yaffs_packedtags2.h
+++ b/yaffs_packedtags2.h
@@ -33,6 +33,11 @@ typedef struct {
 	yaffs_ECCOther ecc;
 } yaffs_PackedTags2;
 
+/* Full packed tags with ECC, used for oob tags */
 void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
 void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
+
+/* Only the tags part (no ECC for use with inband tags */
+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t);
+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt);
 #endif
--- a/yaffs_tagscompat.c
+++ b/yaffs_tagscompat.c
@@ -14,6 +14,7 @@
 #include "yaffs_guts.h"
 #include "yaffs_tagscompat.h"
 #include "yaffs_ecc.h"
+#include "yaffs_getblockinfo.h"
 
 static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
 #ifdef NOTYET
@@ -438,7 +439,7 @@ int yaffs_TagsCompatabilityReadChunkWith
 	yaffs_ECCResult eccResult;
 
 	static yaffs_Spare spareFF;
-	static int init;
+	static int init = 0;
 
 	if (!init) {
 		memset(&spareFF, 0xFF, sizeof(spareFF));
@@ -497,9 +498,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock
 }
 
 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
-					  int blockNo, yaffs_BlockState *
-					  state,
-					  int *sequenceNumber)
+					  int blockNo,
+					  yaffs_BlockState *state,
+					  __u32 *sequenceNumber)
 {
 
 	yaffs_Spare spare0, spare1;
--- a/yaffs_tagscompat.h
+++ b/yaffs_tagscompat.h
@@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWith
 int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
 					    int blockNo);
 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
-					  int blockNo, yaffs_BlockState *
-					  state, int *sequenceNumber);
+					  int blockNo, 
+					  yaffs_BlockState *state,
+					  __u32 *sequenceNumber);
 
 void yaffs_CalcTagsECC(yaffs_Tags * tags);
 int yaffs_CheckECCOnTags(yaffs_Tags * tags);
--- a/yportenv.h
+++ b/yportenv.h
@@ -193,8 +193,8 @@ extern unsigned int yaffs_wr_attempts;
 
 #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
 
-#ifndef CONFIG_YAFFS_WINCE
-#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
+#ifndef YBUG
+#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
 #endif
 
 #endif