From: Charles Manning Date: Wed, 21 Jul 2010 03:23:56 +0000 (+1200) Subject: yaffs Refactor yaffs direct device list management, add nand abstraction, divide... X-Git-Tag: pre-name-change~43 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=4a700fe570d217c2c5df87070db7c2652bc0eaaf yaffs Refactor yaffs direct device list management, add nand abstraction, divide up test code This all makes for a far cleaner layout of test code. The new yaffs direct list management allows partitions to be added synamically rather than statically. This is better for OSs that install partitions at runtime (eg. WInCE). The nand abstraction makes it tidier to add a new nand driver to yaffs direct and test code. The test code has been repartitioned to make porting and file management cleaner. Signed-off-by: Charles Manning --- diff --git a/devextras.h b/devextras.h index 215caa5..ce30c82 100644 --- a/devextras.h +++ b/devextras.h @@ -24,6 +24,8 @@ #define __EXTRAS_H__ +#include "yportenv.h" + #if !(defined __KERNEL__) /* Definition of types */ @@ -33,103 +35,6 @@ 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 ylist_head { - struct ylist_head *next; /* next in chain */ - struct ylist_head *prev; /* previous in chain */ -}; - - -/* Initialise a static list */ -#define YLIST_HEAD(name) \ -struct ylist_head name = { &(name), &(name)} - - - -/* Initialise a list head to an empty list */ -#define YINIT_LIST_HEAD(p) \ -do { \ - (p)->next = (p);\ - (p)->prev = (p); \ -} while (0) - - -/* Add an element to a list */ -static __inline__ void ylist_add(struct ylist_head *newEntry, - struct ylist_head *list) -{ - struct ylist_head *listNext = list->next; - - list->next = newEntry; - newEntry->prev = list; - newEntry->next = listNext; - listNext->prev = newEntry; - -} - -static __inline__ void ylist_add_tail(struct ylist_head *newEntry, - struct ylist_head *list) -{ - struct ylist_head *listPrev = list->prev; - - list->prev = newEntry; - newEntry->next = list; - newEntry->prev = listPrev; - listPrev->next = newEntry; - -} - - -/* Take an element out of its current list, with or without - * reinitialising the links.of the entry*/ -static __inline__ void ylist_del(struct ylist_head *entry) -{ - struct ylist_head *listNext = entry->next; - struct ylist_head *listPrev = entry->prev; - - listNext->prev = listPrev; - listPrev->next = listNext; - -} - -static __inline__ void ylist_del_init(struct ylist_head *entry) -{ - ylist_del(entry); - entry->next = entry->prev = entry; -} - - -/* Test if the list is empty */ -static __inline__ int ylist_empty(struct ylist_head *entry) -{ - return (entry->next == entry); -} - - -/* 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 ylist_entry(entry, type, member) \ - ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member))) - - -/* 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 ylist_for_each(itervar, list) \ - for (itervar = (list)->next; itervar != (list); itervar = itervar->next) - -#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__) diff --git a/direct/Makefile b/direct/basic-test/Makefile similarity index 65% rename from direct/Makefile rename to direct/basic-test/Makefile index 931fed1..d8ddd32 100644 --- a/direct/Makefile +++ b/direct/basic-test/Makefile @@ -28,49 +28,83 @@ CFLAGS += -O0 #CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations #CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline - COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o\ yaffs_nameval.o \ - yaffs_norif1.o ynorsim.o \ - yaffs_allocator.o yaffs_yaffs1.o \ + yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \ + yaffs_allocator.o \ + yaffs_bitmap.o \ + yaffs_yaffs1.o \ yaffs_yaffs2.o \ - yaffs_bitmap.o yaffs_verify.o + yaffs_verify.o # yaffs_checkptrwtest.o\ -DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o +YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o -BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o - -#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o -ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS)) +ALLOBJS = $(sort $(YAFFSTESTOBJS)) -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 \ +YAFFSSYMLINKS = 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_getblockinfo.h \ + yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ - yaffs_nameval.h yaffs_nameval.c \ + yaffs_nameval.c yaffs_nameval.h \ yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \ yaffs_allocator.c yaffs_allocator.h \ - yaffs_bitmap.c yaffs_bitmap.h \ yaffs_yaffs1.c yaffs_yaffs1.h \ yaffs_yaffs2.c yaffs_yaffs2.h \ + yaffs_bitmap.c yaffs_bitmap.h \ yaffs_verify.c yaffs_verify.h -#all: directtest2k boottest +YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ + yaffsfs.h yaffs_malloc.h ydirectenv.h \ + yaffs_flashif.c \ + yaffs_nandif.c yaffs_nandif.h + -all: directtest2k + +SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) + + + + +COMMONTESTOBJS = yaffsnewcfg.o yramsim.o \ + yaffsfs.o yaffs_guts.o yaffs_ecc.o yaffs_nandif.o \ + yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ + yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ + yaffs_checkptrw.o yaffs_qsort.o\ + yaffs_nameval.o \ + yaffs_norif1.o ynorsim.o \ + yaffs_allocator.o yaffs_yaffs1.o \ + yaffs_yaffs2.o \ + yaffs_bitmap.o yaffs_verify.o + +# yaffs_checkptrwtest.o\ + +DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o + +BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o + +ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS)) + +TARGETS = directtest2k + +all: $(TARGETS) $(ALLOBJS): %.o: %.c gcc -c $(CFLAGS) -o $@ $< -$(SYMLINKS): + +$(YAFFSSYMLINKS): + ln -s ../../$@ $@ + +$(YAFFSDIRECTSYMLINKS): ln -s ../$@ $@ + directtest2k: $(SYMLINKS) $(DIRECTTESTOBJS) gcc -o $@ $(DIRECTTESTOBJS) @@ -83,4 +117,4 @@ boottest: $(SYMLINKS) $(BOOTTESTOBJS) clean: - rm -f $(ALLOBJS) core core $(SYMLINKS) + rm -f $(TARGETS) $(ALLOBJS) core core $(SYMLINKS) diff --git a/direct/dtest.c b/direct/basic-test/dtest.c similarity index 100% rename from direct/dtest.c rename to direct/basic-test/dtest.c diff --git a/direct/yaffs_fileem.c b/direct/basic-test/yaffs_fileem.c similarity index 100% rename from direct/yaffs_fileem.c rename to direct/basic-test/yaffs_fileem.c diff --git a/direct/yaffs_fileem2k.c b/direct/basic-test/yaffs_fileem2k.c similarity index 100% rename from direct/yaffs_fileem2k.c rename to direct/basic-test/yaffs_fileem2k.c diff --git a/direct/yaffs_fileem2k.h b/direct/basic-test/yaffs_fileem2k.h similarity index 100% rename from direct/yaffs_fileem2k.h rename to direct/basic-test/yaffs_fileem2k.h diff --git a/direct/yaffs_norif1.c b/direct/basic-test/yaffs_norif1.c similarity index 99% rename from direct/yaffs_norif1.c rename to direct/basic-test/yaffs_norif1.c index ab582b0..ff86747 100644 --- a/direct/yaffs_norif1.c +++ b/direct/basic-test/yaffs_norif1.c @@ -91,6 +91,7 @@ const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.6 2010-02-18 01:18 __u32 *Block2Addr(yaffs_Device *dev, int blockNumber) { __u32 addr; + dev=dev; addr = (__u32) DEVICE_BASE; addr += blockNumber * BLOCK_SIZE_IN_BYTES; @@ -101,7 +102,7 @@ __u32 *Block2Addr(yaffs_Device *dev, int blockNumber) __u32 *Block2FormatAddr(yaffs_Device *dev,int blockNumber) { __u32 addr; - + addr = (__u32) Block2Addr(dev,blockNumber); addr += FORMAT_OFFSET; @@ -301,7 +302,7 @@ int ynorif1_InitialiseNAND(yaffs_Device *dev) int ynorif1_DeinitialiseNAND(yaffs_Device *dev) { - + dev=dev; ynorif1_FlashDeinit(); return YAFFS_OK; diff --git a/direct/yaffs_norif1.h b/direct/basic-test/yaffs_norif1.h similarity index 100% rename from direct/yaffs_norif1.h rename to direct/basic-test/yaffs_norif1.h diff --git a/direct/yaffs_ramdisk.c b/direct/basic-test/yaffs_ramdisk.c similarity index 100% rename from direct/yaffs_ramdisk.c rename to direct/basic-test/yaffs_ramdisk.c diff --git a/direct/yaffs_ramdisk.h b/direct/basic-test/yaffs_ramdisk.h similarity index 100% rename from direct/yaffs_ramdisk.h rename to direct/basic-test/yaffs_ramdisk.h diff --git a/direct/yaffs_ramem2k.c b/direct/basic-test/yaffs_ramem2k.c similarity index 100% rename from direct/yaffs_ramem2k.c rename to direct/basic-test/yaffs_ramem2k.c diff --git a/direct/yaffscfg.c b/direct/basic-test/yaffscfg.c similarity index 98% rename from direct/yaffscfg.c rename to direct/basic-test/yaffscfg.c index 0d83c65..a235bb2 100644 --- a/direct/yaffscfg.c +++ b/direct/basic-test/yaffscfg.c @@ -22,6 +22,9 @@ #include "yaffsfs.h" #include + +#include "yramsim.h" + unsigned yaffs_traceMask = 0xFFFFFFFF; @@ -90,6 +93,9 @@ int yaffs_StartUp(void) // Stuff to initialise anything special (eg lock semaphore). yaffsfs_LocalInitialisation(); +#if 1 + yramsim_CreateSim("yaffs2"); +#else // Set up devices // /ram @@ -135,6 +141,7 @@ int yaffs_StartUp(void) flashDev.initialiseNAND = yflash_InitialiseNAND; yaffs_initialise(yaffsfs_config); +#endif return 0; } diff --git a/direct/yaffscfg.h b/direct/basic-test/yaffscfg.h similarity index 97% rename from direct/yaffscfg.h rename to direct/basic-test/yaffscfg.h index 29417c2..a14797f 100644 --- a/direct/yaffscfg.h +++ b/direct/basic-test/yaffscfg.h @@ -24,6 +24,7 @@ #include "yportenv.h" +#include "devextras.h" #define YAFFSFS_N_HANDLES 100 diff --git a/direct/yaffscfg2k.c b/direct/basic-test/yaffscfg2k.c similarity index 88% rename from direct/yaffscfg2k.c rename to direct/basic-test/yaffscfg2k.c index bfea4f3..b4a4590 100644 --- a/direct/yaffscfg2k.c +++ b/direct/basic-test/yaffscfg2k.c @@ -19,12 +19,14 @@ */ #include "yaffscfg.h" +#include "yaffs_guts.h" #include "yaffsfs.h" #include "yaffs_fileem2k.h" #include "yaffs_nandemul2k.h" #include "yaffs_norif1.h" #include "yaffs_trace.h" + #include unsigned yaffs_traceMask = @@ -104,20 +106,9 @@ void yaffsfs_LocalInitialisation(void) #include "yaffs_flashif2.h" #include "yaffs_nandemul2k.h" -static yaffs_Device ram1Dev; -static yaffs_Device flashDev; -static yaffs_Device ram2kDev; -static yaffs_Device m18_1Dev; - -static yaffsfs_DeviceConfiguration yaffsfs_config[] = { - - { "/ram1", &ram1Dev}, - { "/M18-1", &m18_1Dev}, - { "/yaffs2", &flashDev}, - { "/ram2k", &ram2kDev}, - { NULL, NULL } /* Null entry to terminate list */ -}; - +struct yaffs_DeviceStruct ram1Dev; +struct yaffs_DeviceStruct flashDev; +struct yaffs_DeviceStruct m18_1Dev; int yaffs_StartUp(void) { @@ -128,6 +119,7 @@ int yaffs_StartUp(void) // Set up devices // /ram1 ram, yaffs1 memset(&ram1Dev,0,sizeof(ram1Dev)); + ram1Dev.param.name = "ram1"; ram1Dev.param.totalBytesPerChunk = 512; ram1Dev.param.nChunksPerBlock = 32; ram1Dev.param.nReservedBlocks = 2; // Set this smaller for RAM @@ -135,14 +127,17 @@ int yaffs_StartUp(void) ram1Dev.param.endBlock = 127; // Last block in 2MB. //ram1Dev.param.useNANDECC = 1; ram1Dev.param.nShortOpCaches = 0; // Disable caching on this device. - ram1Dev.context = (void *) 0; // Used to identify the device in fstat. + ram1Dev.driverContext = (void *) 0; // Used to identify the device in fstat. ram1Dev.param.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND; ram1Dev.param.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND; ram1Dev.param.eraseBlockInNAND = yramdisk_EraseBlockInNAND; ram1Dev.param.initialiseNAND = yramdisk_InitialiseNAND; + + yaffs_AddDevice(&ram1Dev); // /M18-1 yaffs1 on M18 nor sim memset(&m18_1Dev,0,sizeof(m18_1Dev)); + m18_1Dev.param.name = "M18-1"; m18_1Dev.param.totalBytesPerChunk = 1024; m18_1Dev.param.nChunksPerBlock =248; m18_1Dev.param.nReservedBlocks = 2; @@ -150,19 +145,20 @@ int yaffs_StartUp(void) m18_1Dev.param.endBlock = 31; // Last block m18_1Dev.param.useNANDECC = 0; // use YAFFS's ECC m18_1Dev.param.nShortOpCaches = 10; // Use caches - m18_1Dev.context = (void *) 1; // Used to identify the device in fstat. + m18_1Dev.driverContext = (void *) 1; // Used to identify the device in fstat. m18_1Dev.param.writeChunkToNAND = ynorif1_WriteChunkToNAND; m18_1Dev.param.readChunkFromNAND = ynorif1_ReadChunkFromNAND; m18_1Dev.param.eraseBlockInNAND = ynorif1_EraseBlockInNAND; m18_1Dev.param.initialiseNAND = ynorif1_InitialiseNAND; m18_1Dev.param.deinitialiseNAND = ynorif1_DeinitialiseNAND; + yaffs_AddDevice(&m18_1Dev); // /yaffs2 yaffs2 file emulation // 2kpage/64chunk per block // memset(&flashDev,0,sizeof(flashDev)); - + flashDev.param.name = "yaffs2"; flashDev.param.totalBytesPerChunk = 2048; flashDev.param.nChunksPerBlock = 64; flashDev.param.nReservedBlocks = 5; @@ -174,7 +170,7 @@ int yaffs_StartUp(void) flashDev.param.wideTnodesDisabled=0; flashDev.param.refreshPeriod = 1000; flashDev.param.nShortOpCaches = 10; // Use caches - flashDev.context = (void *) 2; // Used to identify the device in fstat. + flashDev.driverContext = (void *) 2; // Used to identify the device in fstat. flashDev.param.writeChunkWithTagsToNAND = yflash2_WriteChunkWithTagsToNAND; flashDev.param.readChunkWithTagsFromNAND = yflash2_ReadChunkWithTagsFromNAND; flashDev.param.eraseBlockInNAND = yflash2_EraseBlockInNAND; @@ -183,8 +179,9 @@ int yaffs_StartUp(void) flashDev.param.queryNANDBlock = yflash2_QueryNANDBlock; flashDev.param.enableXattr = 1; + yaffs_AddDevice(&flashDev); - yaffs_initialise(yaffsfs_config); +// todo yaffs_initialise(yaffsfs_config); return 0; } diff --git a/direct/basic-test/yaffsnewcfg.c b/direct/basic-test/yaffsnewcfg.c new file mode 100644 index 0000000..6f1a9e4 --- /dev/null +++ b/direct/basic-test/yaffsnewcfg.c @@ -0,0 +1,112 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2010 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * 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. + */ + +/* + * yaffscfg2k.c The configuration for the "direct" use of yaffs. + * + * This file is intended to be modified to your requirements. + * There is no need to redistribute this file. + */ + +#include "yaffscfg.h" +#include "yaffsfs.h" +#include "yaffs_trace.h" +#include "yramsim.h" + +unsigned yaffs_traceMask = + + YAFFS_TRACE_SCAN | + YAFFS_TRACE_GC | + YAFFS_TRACE_ERASE | + YAFFS_TRACE_ERROR | + YAFFS_TRACE_TRACING | + YAFFS_TRACE_ALLOCATE | + YAFFS_TRACE_BAD_BLOCKS | + YAFFS_TRACE_VERIFY | + + 0; + + +static int yaffsfs_lastError; + +void yaffsfs_SetError(int err) +{ + //Do whatever to set error + yaffsfs_lastError = err; +} + + +int yaffsfs_GetLastError(void) +{ + return yaffsfs_lastError; +} + +void yaffsfs_Lock(void) +{ +} + +void yaffsfs_Unlock(void) +{ +} + +__u32 yaffsfs_CurrentTime(void) +{ + return 0; +} + + +static int yaffs_kill_alloc = 0; +static size_t total_malloced = 0; +static size_t malloc_limit = 0 & 6000000; + +void *yaffs_malloc(size_t size) +{ + void * this; + if(yaffs_kill_alloc) + return NULL; + if(malloc_limit && malloc_limit <(total_malloced + size) ) + return NULL; + + this = malloc(size); + if(this) + total_malloced += size; + return this; +} + +void yaffs_free(void *ptr) +{ + free(ptr); +} + +void yaffsfs_LocalInitialisation(void) +{ + // Define locking semaphore. +} + +// Configuration + + +int yaffs_StartUp(void) +{ + // Stuff to configure YAFFS + // Stuff to initialise anything special (eg lock semaphore). + yaffsfs_LocalInitialisation(); + + yramsim_CreateSim("yaffs2",200); + yramsim_CreateSim("yaffs2-2",50); + + return 0; +} + + + diff --git a/direct/ynorsim.c b/direct/basic-test/ynorsim.c similarity index 100% rename from direct/ynorsim.c rename to direct/basic-test/ynorsim.c diff --git a/direct/ynorsim.h b/direct/basic-test/ynorsim.h similarity index 100% rename from direct/ynorsim.h rename to direct/basic-test/ynorsim.h diff --git a/direct/basic-test/yramsim.c b/direct/basic-test/yramsim.c new file mode 100644 index 0000000..a791791 --- /dev/null +++ b/direct/basic-test/yramsim.c @@ -0,0 +1,277 @@ +// NAND Simulator for testing YAFFS + +#include + +#include "yramsim.h" + +#include "yaffs_nandif.h" + + +#ifdef __WINCE__ +#include +#else +#define DebugBreak() do { } while(0) +#endif + + +#define DATA_SIZE 2048 +#define SPARE_SIZE 64 +#define PAGE_SIZE (DATA_SIZE + SPARE_SIZE) +#define PAGES_PER_BLOCK 64 + + +typedef struct { + unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE]; + unsigned blockOk; +} Block; + +typedef struct { + Block **blockList; + int nBlocks; +} SymData; + + +static SymData *DevToSym(yaffs_Device *dev) +{ + ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext); + SymData * sym = (SymData*)(geom->privateData); + return sym; +} + + +static void CheckInitialised(void) +{ + +} + +static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force) +{ + if(blockId < 0 || blockId >= sym->nBlocks){ + DebugBreak(); + return 0; + } + + if(!sym->blockList[blockId]){ + DebugBreak(); + return 0; + } + + if(!force && !sym->blockList[blockId]->blockOk){ + DebugBreak(); + return 0; + } + + memset(sym->blockList[blockId],0xff,sizeof(Block)); + sym->blockList[blockId]->blockOk = 1; + + return 1; +} + + + + +static int yramsim_Initialise(yaffs_Device *dev) +{ + SymData *sym = DevToSym(dev); + Block **blockList = sym->blockList; + return blockList != NULL; +} + + +static int yramsim_Deinitialise(yaffs_Device *dev) +{ + return 1; +} + +static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId, + unsigned char *data, unsigned dataLength, + unsigned char *spare, unsigned spareLength, + int *eccStatus) +{ + SymData *sym = DevToSym(dev); + Block **blockList = sym->blockList; + + unsigned blockId = pageId / PAGES_PER_BLOCK; + unsigned pageOffset = pageId % PAGES_PER_BLOCK; + unsigned char * d; + unsigned char *s; + if(blockId >= sym->nBlocks || + pageOffset >= PAGES_PER_BLOCK || + dataLength >DATA_SIZE || + spareLength > SPARE_SIZE || + !eccStatus || + !blockList[blockId]->blockOk){ + DebugBreak(); + return 0; + } + + d = blockList[blockId]->page[pageOffset]; + s = d + DATA_SIZE; + + if(data) + memcpy(data,d,dataLength); + + if(spare) + memcpy(spare,s,spareLength); + + *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable + + return 1; + +} + +static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId, + const unsigned char *data, unsigned dataLength, + const unsigned char *spare, unsigned spareLength) +{ + SymData *sym = DevToSym(dev); + Block **blockList = sym->blockList; + + unsigned blockId = pageId / PAGES_PER_BLOCK; + unsigned pageOffset = pageId % PAGES_PER_BLOCK; + unsigned char * d; + unsigned char *s; + if(blockId >= sym->nBlocks || + pageOffset >= PAGES_PER_BLOCK || + dataLength >DATA_SIZE || + spareLength > SPARE_SIZE || + !blockList[blockId]->blockOk){ + DebugBreak(); + return 0; + } + + d = blockList[blockId]->page[pageOffset]; + s = d + DATA_SIZE; + + if(data) + memcpy(d,data,dataLength); + + if(spare) + memcpy(s,spare,spareLength); + + return 1; + +} + + +static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId) +{ + SymData *sym = DevToSym(dev); + + CheckInitialised(); + return yramsim_EraseBlockInternal(sym,blockId,0); +} + +static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId) +{ + SymData *sym = DevToSym(dev); + Block **blockList = sym->blockList; + if(blockId >= sym->nBlocks){ + DebugBreak(); + return 0; + } + + return blockList[blockId]->blockOk ? 1 : 0; +} + +static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId) +{ + SymData *sym = DevToSym(dev); + Block **blockList = sym->blockList; + if(blockId >= sym->nBlocks){ + DebugBreak(); + return 0; + } + + blockList[blockId]->blockOk = 0; + + return 1; +} + + +static SymData *yramsim_AllocSymData(int nBlocks) +{ + int ok = 1; + + Block **blockList; + SymData *sym; + Block *b; + int i; + + sym = malloc(sizeof (SymData)); + if(!sym) + return NULL; + + blockList = malloc(nBlocks * sizeof(Block *)); + + sym->blockList = blockList; + sym->nBlocks = nBlocks; + if(!blockList){ + free(sym); + return NULL; + } + + for(i = 0; i < nBlocks; i++) + blockList[i] = NULL; + + for(i = 0; i < nBlocks && ok; i++){ + b= malloc(sizeof(Block)); + if(b){ + blockList[i] = b; + yramsim_EraseBlockInternal(sym,i,1); + } + else + ok = 0; + } + + if(!ok){ + for(i = 0; i < nBlocks; i++) + if(blockList[i]){ + free(blockList[i]); + blockList[i] = NULL; + } + free(blockList); + blockList = NULL; + free(sym); + sym = NULL; + } + + return sym; +} + + +struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks) +{ + void *sym = (void *)yramsim_AllocSymData(nBlocks); + ynandif_Geometry *g; + + g = YMALLOC(sizeof(ynandif_Geometry)); + + if(!sym || !g){ + if(sym) + YFREE(sym); + if(g) + YFREE(g); + return NULL; + } + + memset(g,0,sizeof(ynandif_Geometry)); + g->startBlock = 0; + g->endBlock = nBlocks - 1; + g->dataSize = DATA_SIZE; + g->spareSize= SPARE_SIZE; + g->pagesPerBlock = PAGES_PER_BLOCK; + g->hasECC = 1; + g->inbandTags = 0; + g->useYaffs2 = 1; + g->initialise = yramsim_Initialise; + g->deinitialise = yramsim_Deinitialise; + g->readChunk = yramsim_ReadChunk, + g->writeChunk = yramsim_WriteChunk, + g->eraseBlock = yramsim_EraseBlock, + g->checkBlockOk = yramsim_CheckBlockOk, + g->markBlockBad = yramsim_MarkBlockBad, + g->privateData = sym; + + return yaffs_AddDeviceFromGeometry(name,g); +} diff --git a/direct/basic-test/yramsim.h b/direct/basic-test/yramsim.h new file mode 100644 index 0000000..694ceaf --- /dev/null +++ b/direct/basic-test/yramsim.h @@ -0,0 +1,11 @@ +// NAND Simulator for testing YAFFS +#ifndef __YAFF_RAM_SIM_H__ +#define __YAFF_RAM_SIM_H__ + + +#include "yaffs_guts.h" + +struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name, int nBlocks); + + +#endif diff --git a/direct/python/Makefile b/direct/python/Makefile index 3c952ee..2f4e5cd 100644 --- a/direct/python/Makefile +++ b/direct/python/Makefile @@ -29,7 +29,9 @@ CFLAGS += -O0 #CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline -COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ +COMMONTESTOBJS = yaffsnewcfg.o yramsim.o \ + yaffs_nandif.o \ + yaffsfs.o yaffs_ecc.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o\ @@ -47,7 +49,7 @@ YAFFSLIBOBJS = $(COMMONTESTOBJS) yaffs_python_helper.o YAFFSSYMLINKS = 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_getblockinfo.h \ + yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ yaffs_nameval.c yaffs_nameval.h \ yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \ @@ -58,14 +60,17 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya yaffs_verify.c yaffs_verify.h -YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ - yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \ - yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\ - yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h \ +YAFFSDIRECTSYMLINKS = yaffsfs.c yaffsfs.h yaffs_malloc.h ydirectenv.h \ + yaffs_flashif.c yaffs_flashif.h\ yaffs_nandif.c yaffs_nandif.h - -SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) +DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffscfg.h yaffs_fileem2k.c yaffs_fileem2k.h\ + yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \ + yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \ + yaffsnewcfg.c yramsim.c yramsim.h \ + ynorsim.h ynorsim.c + +SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS) all: libyaffsfs.so @@ -80,6 +85,8 @@ $(YAFFSSYMLINKS): $(YAFFSDIRECTSYMLINKS): ln -s ../$@ $@ +$(DIRECTEXTRASYMLINKS): + ln -s ../basic-test/$@ $@ libyaffsfs.so: $(SYMLINKS) $(YAFFSLIBOBJS) @@ -89,6 +96,6 @@ libyaffsfs.so: $(SYMLINKS) $(YAFFSLIBOBJS) clean: - rm -f $(YAFFSLIBOBJS) core $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) + rm -f $(YAFFSLIBOBJS) core $(SYMLINKS) rm -f libyaffsfs.so rm -f *.pyc diff --git a/direct/tests/Makefile b/direct/tests/Makefile index 4b92592..e750571 100644 --- a/direct/tests/Makefile +++ b/direct/tests/Makefile @@ -19,7 +19,7 @@ #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC 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 += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing #CFLAGS += -fno-strict-aliasing CFLAGS += -O0 @@ -47,13 +47,11 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o -#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o - ALLOBJS = $(sort $(YAFFSTESTOBJS)) YAFFSSYMLINKS = 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_getblockinfo.h \ + yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h yaffs_list.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ yaffs_nameval.c yaffs_nameval.h \ yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \ @@ -63,14 +61,18 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya yaffs_bitmap.c yaffs_bitmap.h \ yaffs_verify.c yaffs_verify.h -YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ - yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \ - yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\ - yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h \ +YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ + yaffsfs.h yaffs_malloc.h ydirectenv.h \ + yaffs_flashif.c \ yaffs_nandif.c yaffs_nandif.h -SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) +DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffscfg.h yaffs_fileem2k.c yaffs_fileem2k.h\ + yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \ + yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \ + ynorsim.h ynorsim.c + +SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS) #all: directtest2k boottest all: yaffs_test fuzzer @@ -85,6 +87,9 @@ $(YAFFSSYMLINKS): $(YAFFSDIRECTSYMLINKS): ln -s ../$@ $@ +$(DIRECTEXTRASYMLINKS): + ln -s ../basic-test/$@ $@ + yaffs_test: $(SYMLINKS) $(YAFFSTESTOBJS) gcc $(CFLLAG) -o $@ $(YAFFSTESTOBJS) @@ -97,4 +102,4 @@ fuzzer: fuzzer.c clean: - rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) + rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(SYMLINKS) diff --git a/direct/yaffs_nandif.c b/direct/yaffs_nandif.c index 1d33685..6f36eb7 100644 --- a/direct/yaffs_nandif.c +++ b/direct/yaffs_nandif.c @@ -1,244 +1,257 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2010 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * 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. - */ - - - - -#include "yportenv.h" -#include "yaffs_guts.h" -#include "devextras.h" - - -#include "yaffs_nandif.h" -#include "yaffs_packedtags2.h" - - -#if 0 - - -static unsigned char *DevBufferIn(yaffs_Device *dev) -{ - yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice); - return cedev->bufferIn; -} -static unsigned char *DevBufferOut(yaffs_Device *dev) -{ - yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice); - return cedev->bufferOut; -} - -static unsigned DevBufferSize(yaffs_Device *dev) -{ - yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice); - return cedev->bufferSize; -} - -#endif - -/* 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 ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, - const __u8 * data, - const yaffs_ExtendedTags * tags) -{ - - int retval = 0; - yaffs_PackedTags2 pt; - void *spare; - unsigned spareSize = 0; - - unsigned char *bufferIn = DevBufferIn(dev); - unsigned char *bufferOut = DevBufferOut(dev); - unsigned bufferSize = DevBufferSize(dev); - - T(YAFFS_TRACE_MTD, - (TSTR - ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - - - /* 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(dev->inbandTags){ - yaffs_PackedTags2TagsPart *pt2tp; - pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk); - yaffs_PackTags2TagsPart(pt2tp,tags); - spare = NULL; - spareSize = 0; - } - else{ - yaffs_PackTags2(&pt, tags); - spare = &pt; - spareSize = sizeof(yaffs_PackedTags2); - } - - yramsim_WritePage(chunkInNAND, - data, dev->totalBytesPerChunk, spare, spareSize); - - return YAFFS_OK; -} - -int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, - __u8 * data, yaffs_ExtendedTags * tags) -{ - yaffs_PackedTags2 pt; - int localData = 0; - void *spare = NULL; - unsigned spareSize; - int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed - - unsigned char *bufferIn = DevBufferIn(dev); - unsigned char *bufferOut = DevBufferOut(dev); - unsigned bufferSize = DevBufferSize(dev); - - T(YAFFS_TRACE_MTD, - (TSTR - ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - - if(!tags){ - spare = NULL; - spareSize = 0; - }else if(dev->inbandTags){ - - if(!data) { - localData = 1; - data = yaffs_GetTempBuffer(dev,__LINE__); - } - spare = NULL; - spareSize = 0; - } - else { - spare = &pt; - spareSize = sizeof(yaffs_PackedTags2); - } - - yramsim_ReadPage(chunkInNAND, - data,data ? dev->totalBytesPerChunk : 0, - spare,spareSize, - &eccStatus); - - - - if(dev->inbandTags){ - if(tags){ - yaffs_PackedTags2TagsPart * pt2tp; - pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; - yaffs_UnpackTags2TagsPart(tags,pt2tp); - } - } - else { - if (tags){ - yaffs_UnpackTags2(tags, &pt); - } - } - - if(tags && tags->chunkUsed){ - if(eccStatus == 0) - tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR; - else if(eccStatus < 0) - tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; - else - tags->eccResult = YAFFS_ECC_RESULT_FIXED; - } - - if(localData) - yaffs_ReleaseTempBuffer(dev,data,__LINE__); - - return YAFFS_OK; -} - -int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId) -{ - - yramsim_MarkBlockBad(blockId); - - return YAFFS_OK; -} - -int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId) -{ - - yramsim_EraseBlock(blockId); - - return YAFFS_OK; -} - - -static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId) -{ - return yramsim_CheckBlockOk(blockId); -} - -int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber) -{ - unsigned chunkNo; - yaffs_ExtendedTags tags; - - *sequenceNumber = 0; - - chunkNo = blockId * dev->nChunksPerBlock; - - if(!ynandif_IsBlockOk(dev,blockId)){ - *state = YAFFS_BLOCK_STATE_DEAD; - } - else - { - ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); - - if(!tags.chunkUsed) - { - *state = YAFFS_BLOCK_STATE_EMPTY; - } - else - { - *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - *sequenceNumber = tags.sequenceNumber; - } - } - - return YAFFS_OK; -} - - -int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry) -{ - - yramsim_Geometry g; - - yramsim_GetGeometry(&g); - geometry->startBlock = g.startBlock; - geometry->endBlock = g.endBlock; - geometry->dataSize = g.dataSize; - geometry->spareSize = g.spareSize; - geometry->pagesPerBlock = g.pagesPerBlock; - geometry->hasECC = g.hasECC; - geometry->inbandTags = g.inbandTags; - geometry->useYaffs2 = g.useYaffs2; - - return YAFFS_OK; - -} - -int ynandif_InitialiseNAND(yaffs_Device *dev) -{ - - yramsim_Initialise(); - - return YAFFS_OK; -} +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2007 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * 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. + */ + +#include "yportenv.h" +#include "yaffs_guts.h" +#include "devextras.h" + + +#include "yaffs_nandif.h" +#include "yaffs_packedtags2.h" + +#include "yramsim.h" + +#include "yaffs_trace.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 ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, + const __u8 * data, + const yaffs_ExtendedTags * tags) +{ + + int retval = 0; + yaffs_PackedTags2 pt; + void *spare; + unsigned spareSize = 0; + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" + TENDSTR), chunkInNAND, data, tags)); + + + /* 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(dev->param.inbandTags){ + yaffs_PackedTags2TagsPart *pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk); + yaffs_PackTags2TagsPart(pt2tp,tags); + spare = NULL; + spareSize = 0; + } + else{ + yaffs_PackTags2(&pt, tags,!dev->param.noTagsECC); + spare = &pt; + spareSize = sizeof(yaffs_PackedTags2); + } + + retval = geometry->writeChunk(dev,chunkInNAND, + data, dev->param.totalBytesPerChunk, spare, spareSize); + + return retval; +} + +int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, + __u8 * data, yaffs_ExtendedTags * tags) +{ + yaffs_PackedTags2 pt; + int localData = 0; + void *spare = NULL; + unsigned spareSize; + int retval = 0; + int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" + TENDSTR), chunkInNAND, data, tags)); + + if(!tags){ + spare = NULL; + spareSize = 0; + }else if(dev->param.inbandTags){ + + if(!data) { + localData = 1; + data = yaffs_GetTempBuffer(dev,__LINE__); + } + spare = NULL; + spareSize = 0; + } + else { + spare = &pt; + spareSize = sizeof(yaffs_PackedTags2); + } + + retval = geometry->readChunk(dev,chunkInNAND, + data, + data ? dev->param.totalBytesPerChunk : 0, + spare,spareSize, + &eccStatus); + + if(dev->param.inbandTags){ + if(tags){ + yaffs_PackedTags2TagsPart * pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; + yaffs_UnpackTags2TagsPart(tags,pt2tp); + } + } + else { + if (tags){ + yaffs_UnpackTags2(tags, &pt,!dev->param.noTagsECC); + } + } + + if(tags && tags->chunkUsed){ + if(eccStatus < 0 || + tags->eccResult == YAFFS_ECC_RESULT_UNFIXED) + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; + else if(eccStatus > 0 || + tags->eccResult == YAFFS_ECC_RESULT_FIXED) + tags->eccResult = YAFFS_ECC_RESULT_FIXED; + else + tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR; + } + + if(localData) + yaffs_ReleaseTempBuffer(dev,data,__LINE__); + + return retval; +} + +int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId) +{ + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + return geometry->markBlockBad(dev,blockId); +} + +int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId) +{ + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + return geometry->eraseBlock(dev,blockId); + +} + + +static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId) +{ + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + return geometry->checkBlockOk(dev,blockId); +} + +int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber) +{ + unsigned chunkNo; + yaffs_ExtendedTags tags; + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + *sequenceNumber = 0; + + chunkNo = blockId * dev->param.nChunksPerBlock; + + if(!ynandif_IsBlockOk(dev,blockId)){ + *state = YAFFS_BLOCK_STATE_DEAD; + } + else + { + ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); + + if(!tags.chunkUsed) + { + *state = YAFFS_BLOCK_STATE_EMPTY; + } + else + { + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; + *sequenceNumber = tags.sequenceNumber; + } + } + + return YAFFS_OK; +} + + +int ynandif_InitialiseNAND(yaffs_Device *dev) +{ + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + geometry->initialise(dev); + + return YAFFS_OK; +} + +int ynandif_DeinitialiseNAND(yaffs_Device *dev) +{ + ynandif_Geometry *geometry = (ynandif_Geometry *)(dev->driverContext); + + geometry->deinitialise(dev); + + return YAFFS_OK; +} + + +struct yaffs_DeviceStruct * + yaffs_AddDeviceFromGeometry(const YCHAR *name, + const ynandif_Geometry *geometry) +{ + YCHAR *clonedName = YMALLOC(sizeof(YCHAR) * (yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH)+1)); + struct yaffs_DeviceStruct *dev = YMALLOC(sizeof(struct yaffs_DeviceStruct)); + + if(dev && clonedName){ + memset(dev,0,sizeof(struct yaffs_DeviceStruct)); + yaffs_strcpy(clonedName,name); + + dev->param.name = clonedName; + dev->param.writeChunkWithTagsToNAND = ynandif_WriteChunkWithTagsToNAND; + dev->param.readChunkWithTagsFromNAND = ynandif_ReadChunkWithTagsFromNAND; + dev->param.eraseBlockInNAND = ynandif_EraseBlockInNAND; + dev->param.initialiseNAND = ynandif_InitialiseNAND; + dev->param.queryNANDBlock = ynandif_QueryNANDBlock; + dev->param.markNANDBlockBad = ynandif_MarkNANDBlockBad; + dev->param.nShortOpCaches = 20; + dev->param.startBlock = geometry->startBlock; + dev->param.endBlock = geometry->endBlock; + dev->param.totalBytesPerChunk = geometry->dataSize; + dev->param.spareBytesPerChunk = geometry->spareSize; + dev->param.inbandTags = geometry->inbandTags; + dev->param.nChunksPerBlock = geometry->pagesPerBlock; + dev->param.useNANDECC = geometry->hasECC; + dev->param.isYaffs2 = geometry->useYaffs2; + dev->param.nReservedBlocks = 5; + dev->driverContext = (void *)geometry; + + yaffs_AddDevice(dev); + + return dev; + } + + if(dev) + YFREE(dev); + if(clonedName) + YFREE(clonedName); + + return NULL; +} diff --git a/direct/yaffs_nandif.h b/direct/yaffs_nandif.h index f7a67dd..cf4562c 100644 --- a/direct/yaffs_nandif.h +++ b/direct/yaffs_nandif.h @@ -1,7 +1,7 @@ /* * YAFFS: Yet another Flash File System . A NAND-flash specific file system. * - * Copyright (C) 2002-2010 Aleph One Ltd. + * Copyright (C) 2002-2007 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -19,17 +19,47 @@ #include "yaffs_guts.h" + typedef struct { - unsigned startBlock; - unsigned endBlock; - unsigned dataSize; // Number of data bytes per page - unsigned spareSize; // Number of spare bytes per chunk - unsigned pagesPerBlock; - unsigned hasECC; - unsigned inbandTags; // Use inband tags on this device - unsigned useYaffs2; + unsigned startBlock; + unsigned endBlock; + unsigned dataSize; + unsigned spareSize; + unsigned pagesPerBlock; + unsigned hasECC; + unsigned inbandTags; + unsigned useYaffs2; + + int (*initialise)(yaffs_Device *dev); + int (*deinitialise)(yaffs_Device *dev); + + int (*readChunk) (yaffs_Device *dev, + unsigned pageId, + unsigned char *data, unsigned dataLength, + unsigned char *spare, unsigned spareLength, + int *eccStatus); +// ECC status is set to 0 for OK, 1 for fixed, -1 for unfixed. + + int (*writeChunk)(yaffs_Device *dev, + unsigned pageId, + const unsigned char *data, unsigned dataLength, + const unsigned char *spare, unsigned spareLength); + + int (*eraseBlock)(yaffs_Device *dev, unsigned blockId); + + int (*checkBlockOk)(yaffs_Device *dev, unsigned blockId); + int (*markBlockBad)(yaffs_Device *dev, unsigned blockId); + + void *privateData; + } ynandif_Geometry; +struct yaffs_DeviceStruct * + yaffs_AddDeviceFromGeometry(const YCHAR *name, + const ynandif_Geometry *geometry); + +#if 0 + int ynandif_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); int ynandif_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); @@ -38,3 +68,6 @@ int ynandif_MarkNANDBlockBad(yaffs_Device *dev,int blockNumber); int ynandif_QueryNANDBlock(yaffs_Device *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber); int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry); #endif + + +#endif diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 041287c..9fc4417 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -30,13 +30,6 @@ #define YAFFSFS_RW_SHIFT (13) #define YAFFSFS_RW_SIZE (1<prefix && cfg->dev){ + ylist_for_each(cfg, &yaffsfs_deviceList){ + dev = ylist_entry(cfg, yaffs_Device, devList); leftOver = path; - p = cfg->prefix; + p = dev->param.name; thisMatchLength = 0; matching = 1; @@ -319,16 +318,23 @@ static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath) /* Skip over any /s in leftOver */ while(yaffsfs_IsPathDivider(*leftOver)) leftOver++; - - if( matching && (thisMatchLength > longestMatch)){ - /* Matched prefix */ + // Skip over any /s in p + while(yaffsfs_IsPathDivider(*p)) + p++; + + // p should now be at the end of the string (ie. fully matched) + if(*p) + matching = 0; + + if( matching && (thisMatchLength > longestMatch)) + { + // Matched prefix *restOfPath = (YCHAR *)leftOver; - retval = cfg->dev; + retval = dev; longestMatch = thisMatchLength; } - cfg++; } return retval; } @@ -1091,7 +1097,7 @@ static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf) obj = yaffs_GetEquivalentObject(obj); if(obj && buf){ - buf->st_dev = (int)obj->myDev->context; + buf->st_dev = (int)obj->myDev->osContext; buf->st_ino = obj->objectId; buf->st_mode = obj->yst_mode & ~S_IFMT; /* clear out file type bits */ @@ -1859,26 +1865,23 @@ int yaffs_inodecount(const YCHAR *path) } - -void yaffs_initialise(yaffsfs_DeviceConfiguration *cfgList) +void yaffs_AddDevice(yaffs_Device *dev) { + dev->isMounted = 0; + dev->param.removeObjectCallback = yaffsfs_RemoveObjectCallback; - yaffsfs_DeviceConfiguration *cfg; + if(!dev->devList.next) + YINIT_LIST_HEAD(&dev->devList); - yaffsfs_configurationList = cfgList; - - yaffsfs_InitHandles(); - - cfg = yaffsfs_configurationList; + ylist_add(&dev->devList,&yaffsfs_deviceList); +} - while(cfg && cfg->prefix && cfg->dev){ - cfg->dev->isMounted = 0; - cfg->dev->param.removeObjectCallback = yaffsfs_RemoveObjectCallback; - cfg++; - } +void yaffs_RemoveDevice(yaffs_Device *dev) +{ + ylist_del_init(&dev->devList); +} -} /* Directory search stuff. */ diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h index fc9bb9e..7961dff 100644 --- a/direct/yaffsfs.h +++ b/direct/yaffsfs.h @@ -36,165 +36,6 @@ #endif -#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES - -#ifndef O_RDONLY -#define O_RDONLY 00 -#endif - -#ifndef O_WRONLY -#define O_WRONLY 01 -#endif - -#ifndef O_RDWR -#define O_RDWR 02 -#endif - -#ifndef O_CREAT -#define O_CREAT 0100 -#endif - -#ifndef O_EXCL -#define O_EXCL 0200 -#endif - -#ifndef O_TRUNC -#define O_TRUNC 01000 -#endif - -#ifndef O_APPEND -#define O_APPEND 02000 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef EBUSY -#define EBUSY 16 -#endif - -#ifndef ENODEV -#define ENODEV 19 -#endif - -#ifndef EINVAL -#define EINVAL 22 -#endif - -#ifndef EBADF -#define EBADF 9 -#endif - -#ifndef EACCES -#define EACCES 13 -#endif - -#ifndef EXDEV -#define EXDEV 18 -#endif - -#ifndef ENOENT -#define ENOENT 2 -#endif - -#ifndef ENOSPC -#define ENOSPC 28 -#endif - -#ifndef ERANGE -#define ERANGE 34 -#endif - -#ifndef ENODATA -#define ENODATA 61 -#endif - -#ifndef ENOTEMPTY -#define ENOTEMPTY 39 -#endif - -#ifndef ENAMETOOLONG -#define ENAMETOOLONG 36 -#endif - -#ifndef ENOMEM -#define ENOMEM 12 -#endif - -#ifndef EEXIST -#define EEXIST 17 -#endif - -#ifndef ENOTDIR -#define ENOTDIR 20 -#endif - -#ifndef EISDIR -#define EISDIR 21 -#endif - - -// Mode flags - -#ifndef S_IFMT -#define S_IFMT 0170000 -#endif - -#ifndef S_IFLNK -#define S_IFLNK 0120000 -#endif - -#ifndef S_IFDIR -#define S_IFDIR 0040000 -#endif - -#ifndef S_IFREG -#define S_IFREG 0100000 -#endif - -#ifndef S_IREAD -#define S_IREAD 0000400 -#endif - -#ifndef S_IWRITE -#define S_IWRITE 0000200 -#endif - -#ifndef S_IEXEC -#define S_IEXEC 0000100 -#endif - -#ifndef XATTR_CREATE -#define XATTR_CREATE 1 -#endif - -#ifndef XATTR_REPLACE -#define XATTR_REPLACE 2 -#endif - -#ifndef R_OK -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#define F_OK 0 -#endif - -#else -#include -#include -#include -#endif - - struct yaffs_dirent{ long d_ino; /* inode number */ off_t d_off; /* offset to this dirent */ @@ -318,7 +159,8 @@ loff_t yaffs_totalspace(const YCHAR *path); int yaffs_inodecount(const YCHAR *path); - +struct yaffs_DeviceStruct; +void yaffs_AddDevice(struct yaffs_DeviceStruct *dev); int yaffs_StartUp(void); diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index d3e2711..677ab8a 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -22,8 +22,6 @@ // Direct interface -#include "devextras.h" - #include "stdlib.h" #include "stdio.h" #include "string.h" @@ -50,7 +48,7 @@ #ifdef NO_Y_INLINE #define Y_INLINE #else -#define Y_INLINE inline +#define Y_INLINE __inline__ #endif #define YMALLOC(x) yaffs_malloc(x) diff --git a/yaffs_fs.c b/yaffs_fs.c index f0c2771..15096a9 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -438,14 +438,14 @@ static unsigned yaffs_gc_control_callback(yaffs_Device *dev) static void yaffs_GrossLock(yaffs_Device *dev) { T(YAFFS_TRACE_LOCK, (TSTR("yaffs locking %p\n"), current)); - down(&(yaffs_DeviceToContext(dev)->grossLock)); + down(&(yaffs_DeviceToLC(dev)->grossLock)); T(YAFFS_TRACE_LOCK, (TSTR("yaffs locked %p\n"), current)); } static void yaffs_GrossUnlock(yaffs_Device *dev) { T(YAFFS_TRACE_LOCK, (TSTR("yaffs unlocking %p\n"), current)); - up(&(yaffs_DeviceToContext(dev)->grossLock)); + up(&(yaffs_DeviceToLC(dev)->grossLock)); } #ifdef YAFFS_COMPILE_EXPORTFS @@ -560,7 +560,7 @@ static struct yaffs_SearchContext * yaffs_NewSearch(yaffs_Object *dir) dir->variant.directoryVariant.children.next, yaffs_Object,siblings); YINIT_LIST_HEAD(&sc->others); - ylist_add(&sc->others,&(yaffs_DeviceToContext(dev)->searchContexts)); + ylist_add(&sc->others,&(yaffs_DeviceToLC(dev)->searchContexts)); } return sc; } @@ -609,7 +609,7 @@ static void yaffs_RemoveObjectCallback(yaffs_Object *obj) struct ylist_head *i; struct yaffs_SearchContext *sc; - struct ylist_head *search_contexts = &(yaffs_DeviceToContext(obj->myDev)->searchContexts); + struct ylist_head *search_contexts = &(yaffs_DeviceToLC(obj->myDev)->searchContexts); /* Iterate through the directory search contexts. @@ -701,7 +701,7 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev; - if(current != yaffs_DeviceToContext(dev)->readdirProcess) + if(current != yaffs_DeviceToLC(dev)->readdirProcess) yaffs_GrossLock(dev); T(YAFFS_TRACE_OS, @@ -714,7 +714,7 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ /* Can't hold gross lock when calling yaffs_get_inode() */ - if(current != yaffs_DeviceToContext(dev)->readdirProcess) + if(current != yaffs_DeviceToLC(dev)->readdirProcess) yaffs_GrossUnlock(dev); if (obj) { @@ -1435,7 +1435,7 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) yaffs_GrossLock(dev); - yaffs_DeviceToContext(dev)->readdirProcess = current; + yaffs_DeviceToLC(dev)->readdirProcess = current; offset = f->f_pos; @@ -1520,7 +1520,7 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) out: yaffs_EndSearch(sc); - yaffs_DeviceToContext(dev)->readdirProcess = NULL; + yaffs_DeviceToLC(dev)->readdirProcess = NULL; yaffs_GrossUnlock(dev); return retVal; @@ -2100,7 +2100,7 @@ static void yaffs_FlushSuperBlock(struct super_block *sb, int do_checkpoint) static unsigned yaffs_bg_gc_urgency(yaffs_Device *dev) { unsigned erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock; - struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev); + struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev); unsigned scatteredFree = 0; /* Free chunks not in an erased block */ if(erasedChunks < dev->nFreeChunks) @@ -2172,7 +2172,7 @@ void yaffs_background_waker(unsigned long data) static int yaffs_BackgroundThread(void *data) { yaffs_Device *dev = (yaffs_Device *)data; - struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev); + struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev); unsigned long now = jiffies; unsigned long next_dir_update = now; unsigned long next_gc = now; @@ -2251,7 +2251,7 @@ static int yaffs_BackgroundThread(void *data) static int yaffs_BackgroundStart(yaffs_Device *dev) { int retval = 0; - struct yaffs_LinuxContext *context = yaffs_DeviceToContext(dev); + struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev); context->bgRunning = 1; @@ -2268,7 +2268,7 @@ static int yaffs_BackgroundStart(yaffs_Device *dev) static void yaffs_BackgroundStop(yaffs_Device *dev) { - struct yaffs_LinuxContext *ctxt = yaffs_DeviceToContext(dev); + struct yaffs_LinuxContext *ctxt = yaffs_DeviceToLC(dev); ctxt->bgRunning = 0; @@ -2380,14 +2380,14 @@ static void yaffs_read_inode(struct inode *inode) T(YAFFS_TRACE_OS, (TSTR("yaffs_read_inode for %d\n"), (int)inode->i_ino)); - if(current != yaffs_DeviceToContext(dev)->readdirProcess) + if(current != yaffs_DeviceToLC(dev)->readdirProcess) yaffs_GrossLock(dev); obj = yaffs_FindObjectByNumber(dev, inode->i_ino); yaffs_FillInodeFromObject(inode, obj); - if(current != yaffs_DeviceToContext(dev)->readdirProcess) + if(current != yaffs_DeviceToLC(dev)->readdirProcess) yaffs_GrossUnlock(dev); } @@ -2396,34 +2396,6 @@ static void yaffs_read_inode(struct inode *inode) static YLIST_HEAD(yaffs_context_list); struct semaphore yaffs_context_lock; -#if 0 /* not used */ -static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) -{ - yaffs_Device *dev = yaffs_SuperToDevice(sb); - - if (*flags & MS_RDONLY) { - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; - - T(YAFFS_TRACE_OS, - (TSTR("yaffs_remount_fs: %s: RO\n"), dev->name)); - - yaffs_GrossLock(dev); - - yaffs_FlushSuperBlock(sb,1); - - if (mtd->sync) - mtd->sync(mtd); - - yaffs_GrossUnlock(dev); - } else { - T(YAFFS_TRACE_OS, - (TSTR("yaffs_remount_fs: %s: RW\n"), dev->name)); - } - - return 0; -} -#endif - static void yaffs_put_super(struct super_block *sb) { yaffs_Device *dev = yaffs_SuperToDevice(sb); @@ -2440,8 +2412,8 @@ static void yaffs_put_super(struct super_block *sb) yaffs_FlushSuperBlock(sb,1); - if (yaffs_DeviceToContext(dev)->putSuperFunc) - yaffs_DeviceToContext(dev)->putSuperFunc(sb); + if (yaffs_DeviceToLC(dev)->putSuperFunc) + yaffs_DeviceToLC(dev)->putSuperFunc(sb); yaffs_Deinitialise(dev); @@ -2449,12 +2421,12 @@ static void yaffs_put_super(struct super_block *sb) yaffs_GrossUnlock(dev); down(&yaffs_context_lock); - ylist_del_init(&(yaffs_DeviceToContext(dev)->contextList)); + ylist_del_init(&(yaffs_DeviceToLC(dev)->contextList)); up(&yaffs_context_lock); - if (yaffs_DeviceToContext(dev)->spareBuffer) { - YFREE(yaffs_DeviceToContext(dev)->spareBuffer); - yaffs_DeviceToContext(dev)->spareBuffer = NULL; + if (yaffs_DeviceToLC(dev)->spareBuffer) { + YFREE(yaffs_DeviceToLC(dev)->spareBuffer); + yaffs_DeviceToLC(dev)->spareBuffer = NULL; } kfree(dev); @@ -2463,7 +2435,7 @@ static void yaffs_put_super(struct super_block *sb) static void yaffs_MTDPutSuper(struct super_block *sb) { - struct mtd_info *mtd = yaffs_DeviceToContext(yaffs_SuperToDevice(sb))->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(yaffs_SuperToDevice(sb)); if (mtd->sync) mtd->sync(mtd); @@ -2474,7 +2446,7 @@ static void yaffs_MTDPutSuper(struct super_block *sb) static void yaffs_MarkSuperBlockDirty(yaffs_Device *dev) { - struct super_block *sb = yaffs_DeviceToContext(dev)->superBlock; + struct super_block *sb = yaffs_DeviceToLC(dev)->superBlock; T(YAFFS_TRACE_OS, (TSTR("yaffs_MarkSuperBlockDirty() sb = %p\n"), sb)); if (sb) @@ -2759,7 +2731,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, param = &(dev->param); memset(context,0,sizeof(struct yaffs_LinuxContext)); - dev->context = context; + dev->osContext = context; YINIT_LIST_HEAD(&(context->contextList)); context->dev = dev; context->superBlock = sb; @@ -2772,7 +2744,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, sb->u.generic_sbp = dev; #endif - yaffs_DeviceToContext(dev)->mtd = mtd; + dev->driverContext = mtd; param->name = mtd->name; /* Set up the memory size parameters.... */ @@ -2829,7 +2801,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, nandmtd2_ReadChunkWithTagsFromNAND; param->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; param->queryNANDBlock = nandmtd2_QueryNANDBlock; - yaffs_DeviceToContext(dev)->spareBuffer = YMALLOC(mtd->oobsize); + yaffs_DeviceToLC(dev)->spareBuffer = YMALLOC(mtd->oobsize); param->isYaffs2 = 1; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) param->totalBytesPerChunk = mtd->writesize; @@ -2861,12 +2833,12 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, param->eraseBlockInNAND = nandmtd_EraseBlockInNAND; param->initialiseNAND = nandmtd_InitialiseNAND; - yaffs_DeviceToContext(dev)->putSuperFunc = yaffs_MTDPutSuper; + yaffs_DeviceToLC(dev)->putSuperFunc = yaffs_MTDPutSuper; param->markSuperBlockDirty = yaffs_MarkSuperBlockDirty; param->gcControl = yaffs_gc_control_callback; - yaffs_DeviceToContext(dev)->superBlock= sb; + yaffs_DeviceToLC(dev)->superBlock= sb; #ifndef CONFIG_YAFFS_DOES_ECC @@ -2893,14 +2865,14 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, } context->mount_id = mount_id; - ylist_add_tail(&(yaffs_DeviceToContext(dev)->contextList), &yaffs_context_list); + ylist_add_tail(&(yaffs_DeviceToLC(dev)->contextList), &yaffs_context_list); up(&yaffs_context_lock); /* Directory search handling...*/ - YINIT_LIST_HEAD(&(yaffs_DeviceToContext(dev)->searchContexts)); + YINIT_LIST_HEAD(&(yaffs_DeviceToLC(dev)->searchContexts)); param->removeObjectCallback = yaffs_RemoveObjectCallback; - init_MUTEX(&(yaffs_DeviceToContext(dev)->grossLock)); + init_MUTEX(&(yaffs_DeviceToLC(dev)->grossLock)); yaffs_GrossLock(dev); diff --git a/yaffs_guts.c b/yaffs_guts.c index a8b850a..d65c0ca 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -99,6 +99,11 @@ static int yaffs_VerifyChunkWritten(yaffs_Device *dev, const __u8 *data, yaffs_ExtendedTags *tags); + +static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize); +static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev,YCHAR *ohName, const YCHAR *name); + + /* Function to calculate chunk and offset */ static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, @@ -622,6 +627,18 @@ void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) obj->sum = yaffs_CalcNameSum(name); } +void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh) +{ +#ifdef CONFIG_YAFFS_AUTO_UNICODE + YCHAR tmpName[YAFFS_MAX_NAME_LENGTH+1]; + memset(tmpName,0,sizeof(tmpName)); + yaffs_LoadNameFromObjectHeader(obj->myDev,tmpName,oh->name,YAFFS_MAX_NAME_LENGTH+1); + yaffs_SetObjectName(obj,tmpName); +#else + yaffs_SetObjectName(obj,oh->name); +#endif +} + /*-------------------- TNODES ------------------- * List of spare tnodes @@ -3036,7 +3053,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, if (name && *name) { memset(oh->name, 0, sizeof(oh->name)); - yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); + yaffs_LoadObjectHeaderFromName(dev,oh->name,name); } else if (prevChunkId > 0) memcpy(oh->name, oldName, sizeof(oh->name)); else @@ -4386,6 +4403,7 @@ static void yaffs_UpdateParent(yaffs_Object *obj) yaffs_Device *dev; if(!obj) return; +#ifndef CONFIG_YAFFS_WINCE dev = obj->myDev; obj->dirty = 1; @@ -4400,6 +4418,7 @@ static void yaffs_UpdateParent(yaffs_Object *obj) } else yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL); +#endif } void yaffs_UpdateDirtyDirectories(yaffs_Device *dev) @@ -4600,36 +4619,124 @@ yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj) return obj; } -int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize) -{ - memset(name, 0, buffSize * sizeof(YCHAR)); - - yaffs_CheckObjectDetailsLoaded(obj); +/* + * A note or two on object names. + * * If the object name is missing, we then make one up in the form objnnn + * + * * ASCII names are stored in the object header's name field from byte zero + * * Unicode names are historically stored starting from byte zero. + * + * Then there are automatic Unicode names... + * The purpose of these is to save names in a way that can be read as + * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII + * system to share files. + * + * These automatic unicode are stored slightly differently... + * - If the name can fit in the ASCII character space then they are saved as + * ascii names as per above. + * - If the name needs Unicode then the name is saved in Unicode + * starting at oh->name[1]. - if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { - yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); - } else if (obj->hdrChunk <= 0) { + */ +static void yaffs_FixNullName(yaffs_Object * obj,YCHAR * name, int buffSize) +{ + /* Create an object name if we could not find one. */ + if(yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH) == 0){ YCHAR locName[20]; YCHAR numString[20]; YCHAR *x = &numString[19]; unsigned v = obj->objectId; numString[19] = 0; - while (v > 0) { + while(v>0){ x--; *x = '0' + (v % 10); v /= 10; } /* make up a name */ yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX); - yaffs_strcat(locName, x); + yaffs_strcat(locName,x); yaffs_strncpy(name, locName, buffSize - 1); + } +} + +static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize) +{ +#ifdef CONFIG_YAFFS_AUTO_UNICODE + if(dev->param.autoUnicode){ + if(*ohName){ + /* It is an ASCII name, so do an ASCII to unicode conversion */ + const char *asciiOhName = (const char *)ohName; + int n = bufferSize - 1; + while(n > 0 && *asciiOhName){ + *name = *asciiOhName; + name++; + asciiOhName++; + n--; + } + } else + yaffs_strncpy(name,ohName+1, bufferSize -1); + } else +#endif + yaffs_strncpy(name, ohName, bufferSize - 1); +} + + +static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev, YCHAR *ohName, const YCHAR *name) +{ +#ifdef CONFIG_YAFFS_AUTO_UNICODE + + int isAscii; + YCHAR *w; + + if(dev->param.autoUnicode){ + isAscii = 1; + w = name; + + /* Figure out if the name will fit in ascii character set */ + while(isAscii && *w){ + if((*w) & 0xff00) + isAscii = 0; + w++; + } + + if(isAscii){ + /* It is an ASCII name, so do a unicode to ascii conversion */ + char *asciiOhName = (char *)ohName; + int n = YAFFS_MAX_NAME_LENGTH - 1; + while(n > 0 && *name){ + *asciiOhName= *name; + name++; + asciiOhName++; + n--; + } + } else{ + /* It is a unicode name, so save starting at the second YCHAR */ + *ohName = 0; + yaffs_strncpy(ohName+1,name, YAFFS_MAX_NAME_LENGTH -2); + } } + else +#endif + yaffs_strncpy(ohName,name, YAFFS_MAX_NAME_LENGTH - 1); + +} + +int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) +{ + memset(name, 0, buffSize * sizeof(YCHAR)); + + yaffs_CheckObjectDetailsLoaded(obj); + + if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { + yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); + } #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM - else if (obj->shortName[0]) - yaffs_strncpy(name, obj->shortName,YAFFS_SHORT_NAME_LENGTH+1); + else if (obj->shortName[0]) { + yaffs_strcpy(name, obj->shortName); + } #endif - else { + else if(obj->hdrChunk > 0) { int result; __u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__); @@ -4642,15 +4749,17 @@ int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize) obj->hdrChunk, buffer, NULL); } - yaffs_strncpy(name, oh->name, buffSize - 1); - name[buffSize-1]=0; + yaffs_LoadNameFromObjectHeader(obj->myDev,name,oh->name,buffSize); yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__); } - return yaffs_strnlen(name,buffSize-1); + yaffs_FixNullName(obj,name,buffSize); + + return yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH); } + int yaffs_GetObjectFileLength(yaffs_Object *obj) { /* Dereference any hard linking */ diff --git a/yaffs_guts.h b/yaffs_guts.h index c6e49c4..b7e2f4b 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -16,8 +16,9 @@ #ifndef __YAFFS_GUTS_H__ #define __YAFFS_GUTS_H__ -#include "devextras.h" #include "yportenv.h" +#include "devextras.h" +#include "yaffs_list.h" #define YAFFS_OK 1 #define YAFFS_FAIL 0 @@ -598,6 +599,10 @@ struct yaffs_DeviceParamStruct { int disableSoftDelete; /* yaffs 1 only: Set to disable the use of softdeletion. */ int deferDirectoryUpdate; /* Set to defer directory updates */ + +#ifdef CONFIG_YAFFS_AUTO_UNICODE + int autoUnicode; +#endif }; @@ -608,7 +613,10 @@ struct yaffs_DeviceStruct { /* Context storage. Holds extra OS specific data for this device */ - void *context; + void *osContext; + void *driverContext; + + struct ylist_head devList; /* Runtime parameters. Set up by YAFFS. */ int nDataBytesPerChunk; @@ -928,6 +936,7 @@ yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, int chunkInNAND, int inScan); void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name); +void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh); void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj); YCHAR *yaffs_CloneString(const YCHAR *str); diff --git a/yaffs_linux.h b/yaffs_linux.h index 6832681..ce059fd 100644 --- a/yaffs_linux.h +++ b/yaffs_linux.h @@ -29,7 +29,6 @@ struct yaffs_LinuxContext { __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer * at compile time so we have to allocate it. */ - struct mtd_info *mtd; struct ylist_head searchContexts; void (*putSuperFunc)(struct super_block *sb); @@ -37,7 +36,8 @@ struct yaffs_LinuxContext { unsigned mount_id; }; -#define yaffs_DeviceToContext(dev) ((struct yaffs_LinuxContext *)((dev)->context)) +#define yaffs_DeviceToLC(dev) ((struct yaffs_LinuxContext *)((dev)->osContext)) +#define yaffs_DeviceToMtd(dev) ((struct mtd_info *)((dev)->driverContext)) #endif diff --git a/yaffs_list.h b/yaffs_list.h new file mode 100644 index 0000000..09d80b8 --- /dev/null +++ b/yaffs_list.h @@ -0,0 +1,127 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2010 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + +/* + * This file is just holds extra declarations of macros that would normally + * be providesd in the Linux kernel. These macros have been written from + * scratch but are functionally equivalent to the Linux ones. + * + */ + +#ifndef __YAFFS_LIST_H__ +#define __YAFFS_LIST_H__ + + +#include "yportenv.h" + +/* + * This is a simple doubly linked list implementation that matches the + * way the Linux kernel doubly linked list implementation works. + */ + +struct ylist_head { + struct ylist_head *next; /* next in chain */ + struct ylist_head *prev; /* previous in chain */ +}; + + +/* Initialise a static list */ +#define YLIST_HEAD(name) \ +struct ylist_head name = { &(name), &(name)} + + + +/* Initialise a list head to an empty list */ +#define YINIT_LIST_HEAD(p) \ +do { \ + (p)->next = (p);\ + (p)->prev = (p); \ +} while (0) + + +/* Add an element to a list */ +static Y_INLINE void ylist_add(struct ylist_head *newEntry, + struct ylist_head *list) +{ + struct ylist_head *listNext = list->next; + + list->next = newEntry; + newEntry->prev = list; + newEntry->next = listNext; + listNext->prev = newEntry; + +} + +static Y_INLINE void ylist_add_tail(struct ylist_head *newEntry, + struct ylist_head *list) +{ + struct ylist_head *listPrev = list->prev; + + list->prev = newEntry; + newEntry->next = list; + newEntry->prev = listPrev; + listPrev->next = newEntry; + +} + + +/* Take an element out of its current list, with or without + * reinitialising the links.of the entry*/ +static Y_INLINE void ylist_del(struct ylist_head *entry) +{ + struct ylist_head *listNext = entry->next; + struct ylist_head *listPrev = entry->prev; + + listNext->prev = listPrev; + listPrev->next = listNext; + +} + +static Y_INLINE void ylist_del_init(struct ylist_head *entry) +{ + ylist_del(entry); + entry->next = entry->prev = entry; +} + + +/* Test if the list is empty */ +static Y_INLINE int ylist_empty(struct ylist_head *entry) +{ + return (entry->next == entry); +} + + +/* 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 ylist_entry(entry, type, member) \ + ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member))) + + +/* 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 ylist_for_each(itervar, list) \ + for (itervar = (list)->next; itervar != (list); itervar = itervar->next) + +#define ylist_for_each_safe(itervar, saveVar, list) \ + for (itervar = (list)->next, saveVar = (list)->next->next; \ + itervar != (list); itervar = saveVar, saveVar = saveVar->next) + + +#endif diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c index 5de3193..e073a5e 100644 --- a/yaffs_mtdif.c +++ b/yaffs_mtdif.c @@ -25,7 +25,7 @@ int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); __u32 addr = ((loff_t) blockNumber) * dev->param.totalBytesPerChunk * dev->param.nChunksPerBlock; diff --git a/yaffs_mtdif1.c b/yaffs_mtdif1.c index aaa02db..b14a254 100644 --- a/yaffs_mtdif1.c +++ b/yaffs_mtdif1.c @@ -91,7 +91,7 @@ static struct nand_ecclayout nand_oob_16 = { int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int chunkBytes = dev->nDataBytesPerChunk; loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; struct mtd_oob_ops ops; @@ -169,7 +169,7 @@ static int rettags(yaffs_ExtendedTags *etags, int eccResult, int retval) int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int chunkBytes = dev->nDataBytesPerChunk; loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; int eccres = YAFFS_ECC_RESULT_NO_ERROR; @@ -280,7 +280,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, */ int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int blocksize = dev->param.nChunksPerBlock * dev->nDataBytesPerChunk; int retval; @@ -321,7 +321,7 @@ static int nandmtd1_TestPrerequists(struct mtd_info *mtd) int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *pState, __u32 *pSequenceNumber) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int chunkNo = blockNo * dev->param.nChunksPerBlock; loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk; yaffs_ExtendedTags etags; diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index c1d4478..2b0a601 100644 --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -34,7 +34,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *tags) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); #if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) struct mtd_oob_ops ops; #else @@ -100,7 +100,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); #if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) struct mtd_oob_ops ops; #endif @@ -141,7 +141,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size; ops.ooboffs = 0; ops.datbuf = data; - ops.oobbuf = yaffs_DeviceToContext(dev)->spareBuffer; + ops.oobbuf = yaffs_DeviceToLC(dev)->spareBuffer; retval = mtd->read_oob(mtd, addr, &ops); } #else @@ -171,7 +171,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, } } else { if (tags) { - memcpy(packed_tags_ptr, yaffs_DeviceToContext(dev)->spareBuffer, packed_tags_size); + memcpy(packed_tags_ptr, yaffs_DeviceToLC(dev)->spareBuffer, packed_tags_size); yaffs_UnpackTags2(tags, &pt, !dev->param.noTagsECC); } } @@ -195,7 +195,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int retval; T(YAFFS_TRACE_MTD, (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); @@ -215,7 +215,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber) { - struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd; + struct mtd_info *mtd = yaffs_DeviceToMtd(dev); int retval; T(YAFFS_TRACE_MTD, diff --git a/yaffs_yaffs1.c b/yaffs_yaffs1.c index bcfd594..1b8fcf1 100644 --- a/yaffs_yaffs1.c +++ b/yaffs_yaffs1.c @@ -305,7 +305,7 @@ int yaffs1_Scan(yaffs_Device *dev) in->hdrChunk = chunk; in->serial = tags.serialNumber; - yaffs_SetObjectName(in, oh->name); + yaffs_SetObjectNameFromOH(in, oh); in->dirty = 0; /* directory stuff... diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index 90646fd..ab175b9 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -1373,7 +1373,7 @@ int yaffs2_ScanBackwards(yaffs_Device *dev) - yaffs_SetObjectName(in, oh->name); + yaffs_SetObjectNameFromOH(in, oh); parent = yaffs_FindOrCreateObjectByNumber (dev, oh->parentObjectId, diff --git a/yportenv.h b/yportenv.h index 687f5e6..cb79d9b 100644 --- a/yportenv.h +++ b/yportenv.h @@ -60,7 +60,7 @@ #define yaffs_sprintf sprintf #define yaffs_toupper(a) toupper(a) -#define Y_INLINE inline +#define Y_INLINE __inline__ #define YAFFS_LOSTNFOUND_NAME "lost+found" #define YAFFS_LOSTNFOUND_PREFIX "obj" @@ -112,7 +112,6 @@ #include "stdio.h" #include "string.h" -#include "devextras.h" #define YMALLOC(x) malloc(x) #define YFREE(x) free(x) @@ -154,6 +153,168 @@ #endif +#if defined(CONFIG_YAFFS_DIRECT) || defined(CONFIG_YAFFS_WINCE) + +#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES + +#ifndef O_RDONLY +#define O_RDONLY 00 +#endif + +#ifndef O_WRONLY +#define O_WRONLY 01 +#endif + +#ifndef O_RDWR +#define O_RDWR 02 +#endif + +#ifndef O_CREAT +#define O_CREAT 0100 +#endif + +#ifndef O_EXCL +#define O_EXCL 0200 +#endif + +#ifndef O_TRUNC +#define O_TRUNC 01000 +#endif + +#ifndef O_APPEND +#define O_APPEND 02000 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef EBUSY +#define EBUSY 16 +#endif + +#ifndef ENODEV +#define ENODEV 19 +#endif + +#ifndef EINVAL +#define EINVAL 22 +#endif + +#ifndef EBADF +#define EBADF 9 +#endif + +#ifndef EACCES +#define EACCES 13 +#endif + +#ifndef EXDEV +#define EXDEV 18 +#endif + +#ifndef ENOENT +#define ENOENT 2 +#endif + +#ifndef ENOSPC +#define ENOSPC 28 +#endif + +#ifndef ERANGE +#define ERANGE 34 +#endif + +#ifndef ENODATA +#define ENODATA 61 +#endif + +#ifndef ENOTEMPTY +#define ENOTEMPTY 39 +#endif + +#ifndef ENAMETOOLONG +#define ENAMETOOLONG 36 +#endif + +#ifndef ENOMEM +#define ENOMEM 12 +#endif + +#ifndef EEXIST +#define EEXIST 17 +#endif + +#ifndef ENOTDIR +#define ENOTDIR 20 +#endif + +#ifndef EISDIR +#define EISDIR 21 +#endif + + +// Mode flags + +#ifndef S_IFMT +#define S_IFMT 0170000 +#endif + +#ifndef S_IFLNK +#define S_IFLNK 0120000 +#endif + +#ifndef S_IFDIR +#define S_IFDIR 0040000 +#endif + +#ifndef S_IFREG +#define S_IFREG 0100000 +#endif + +#ifndef S_IREAD +#define S_IREAD 0000400 +#endif + +#ifndef S_IWRITE +#define S_IWRITE 0000200 +#endif + +#ifndef S_IEXEC +#define S_IEXEC 0000100 +#endif + +#ifndef XATTR_CREATE +#define XATTR_CREATE 1 +#endif + +#ifndef XATTR_REPLACE +#define XATTR_REPLACE 2 +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#define F_OK 0 +#endif + +#else +#include +#include +#include +#endif + +#endif + #ifndef Y_DUMP_STACK #define Y_DUMP_STACK() do { } while (0) #endif @@ -167,4 +328,5 @@ } while (0) #endif + #endif