-/*\r
- * YAFFS: Yet another FFS. A NAND-flash specific file system.\r
- * yaffsfsd.c: FSD interface funtions for WinCE.\r
- *\r
- * Copyright (C) 2002 Trimble Navigation Ltd.\r
- *\r
- * Created by Charles Manning <charles.manning@trimble.co.nz>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License version 2 as\r
- * published by the Free Software Foundation.\r
- *\r
- * This program is distributed in the hope that it will be useful, \r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of \r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \r
- * General Public License for more details. You should have received a \r
- * copy of the GNU General Public License along with this program; \r
- * if not, write to the Free Software Foundation, Inc., \r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \r
- *\r
- * Acknowledgements:\r
- * Various clean-ups and WinCE4 support by Steve Fogle and Lynn Winter\r
- * $Id: yaffsfsd.c,v 1.3 2003-01-31 00:52:53 charles Exp $\r
- */\r
-#include <windows.h>\r
-#include <extfile.h>\r
-#include <yaffs_guts.h>\r
-#include <ynandif.h>\r
-//slf021104b begin\r
-#include <diskio.h>\r
-//slf021104b end\r
-\r
-#define MAX_WIN_FILE 200\r
-#define YFSD_NAME_LENGTH 128\r
-#define YFSD_FULL_PATH_NAME_SIZE 500\r
-\r
-\r
-#define YFSD_DISK_NAME L"Disk"\r
-#define YFSD_BOOT_NAME L"Boot"\r
-\r
-#define PARTITION_START_NUMBER (1280) \r
-\r
-\r
-// if this is defined the there will be a constant message box raised to display status\r
-//#define MSGBOX_DISPLAY\r
- \r
-\r
-//#define MSGSTATE 1\r
-#define MSGSTATE 0\r
-//#define DISABLE_BOOT_PARTITION\r
-//slf021105a begin\r
-// Define DO_PARTITION_TABLE to cause the partition table \r
-// information to be retrieved from the block driver.\r
-// Can define this in your sources file.\r
-//#define DO_PARTITION_TABLE\r
-// How many partitions the disk might have. 2 gives \r
-// space for the "Disk" and "Boot" partitions.\r
-#define MAXPARTITIONS (2)\r
-//slf021105a end\r
-\r
-//unsigned yaffs_traceMask=0xffffffff;\r
-unsigned yaffs_traceMask=0;\r
-\r
-\r
-typedef struct\r
-{\r
- yaffs_Device dev;\r
- DWORD hdsk;\r
- DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL\r
- BOOL isMounted;\r
- BOOL configured;\r
-// DWORD guard0[100];\r
-// DWORD guard1[100];\r
- SHELLFILECHANGEFUNC_t shellFunction;\r
- PWSTR volName;\r
-} yfsd_Volume;\r
-\r
-typedef struct \r
-{\r
- yaffs_Object *obj;\r
- DWORD offset;\r
- BOOL isopen;\r
- BOOL dirty;\r
- WCHAR *fullName;\r
- yfsd_Volume *myVolume;\r
- BOOL writePermitted;\r
- BOOL readPermitted;\r
- BOOL shareRead;\r
- BOOL shareWrite;\r
-\r
-} yfsd_WinFile;\r
-\r
-struct yfsd_FoundObjectStruct\r
-{\r
- yaffs_Object *obj;\r
- struct yfsd_FoundObjectStruct *next;\r
-};\r
-\r
-typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;\r
-\r
-typedef struct \r
-{\r
- yaffs_Object *dir;\r
- char pattern[YFSD_NAME_LENGTH+1];\r
- yaffs_FoundObject *foundObjects;\r
-} yfsd_WinFind;\r
-\r
-\r
-\r
-#define PSEARCH yfsd_WinFind*\r
-\r
-#define PVOLUME yfsd_Volume*\r
-#define PFILE yfsd_WinFile*\r
-\r
-#define FSD_API YFSD\r
-\r
-#include <fsdmgr.h>\r
-\r
-//slf021105a begin\r
-//static yfsd_Volume disk_volume;\r
-//static yfsd_Volume boot_volume;\r
-static yfsd_Volume * disk_volumes[MAXPARTITIONS];\r
-//slf021105a end;\r
-\r
-static CRITICAL_SECTION yaffsLock;\r
-static CRITICAL_SECTION winFileLock;\r
-\r
-static int yaffsLockInited = 0;\r
-\r
-static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];\r
-\r
-#if 0\r
-static yfsd_SetGuards(void)\r
-{\r
- int i;\r
- for(i = 0; i < 100; i++)\r
- {\r
- yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;\r
- }\r
-}\r
-\r
-static void yfsd_CheckGuards(void)\r
-{\r
- int i;\r
- int found;\r
- for(i = found = 0; i < 100 && !found; i++)\r
- {\r
- if(yfsd_volume.guard0[i] != i)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));\r
- found = 1;\r
- }\r
- if(yfsd_volume.guard1[i] != i)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));\r
- found = 1;\r
- }\r
- }\r
-}\r
-#endif\r
-\r
-\r
-#ifdef MSGBOX_DISPLAY\r
-DWORD WINAPI yfsd_MessageThread(LPVOID param)\r
-{\r
- yaffs_Device *dev = (yaffs_Device *)param;\r
- TCHAR dataBuffer[1000];\r
- Sleep(10000);\r
-\r
- // note : if the device gets free'd from under us, we will cause an exception in the loop\r
- while (1)\r
- {\r
- wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"\r
- L"nErasedBlocks %i\r\n"\r
- L"allocationBlock %i\r\n"\r
- L"allocationPage %i\r\n"\r
- L"garbageCollectionRequired %i\r\n"\r
- L"nRetiredBlocks %i\r\n"\r
- L"cacheHits %i\r\n"\r
- L"eccFixed %i\r\n"\r
- L"eccUnfixed %i\r\n"\r
- L"tagsEccFixed %i\r\n"\r
- L"tagsEccUnfixed %i\r\n",\r
- dev->nShortOpCaches, \r
- dev->nErasedBlocks,\r
- dev->allocationBlock,\r
- dev->allocationPage,\r
- dev->garbageCollectionRequired,\r
- dev->nRetiredBlocks,\r
- dev->cacheHits,\r
- dev->eccFixed,\r
- dev->eccUnfixed,\r
- dev->tagsEccFixed,\r
- dev->tagsEccUnfixed);\r
-\r
- MessageBox(NULL,\r
- dataBuffer,\r
- L"YAFFS PROC INFO",\r
- MB_OK);\r
- Sleep(1);\r
- }\r
-}\r
-#endif\r
-\r
-void yfsd_LockWinFiles(void)\r
-{\r
- //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));\r
- EnterCriticalSection(&winFileLock);\r
-}\r
-void yfsd_UnlockWinFiles(void)\r
-{\r
- //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));\r
- LeaveCriticalSection(&winFileLock);\r
-}\r
-\r
-int lockwaits;\r
-\r
-void yfsd_LockYAFFS(void)\r
-{\r
- //yfsd_CheckGuards();\r
- //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));\r
- lockwaits++;\r
- EnterCriticalSection(&yaffsLock);\r
- //RETAILMSG (MSGSTATE, (L" locked\r\n"));\r
-}\r
-void yfsd_UnlockYAFFS(void)\r
-{\r
- //yfsd_CheckGuards();\r
- //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));\r
- LeaveCriticalSection(&yaffsLock);\r
- lockwaits--;\r
- //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));\r
-}\r
-\r
-\r
-void yfsd_InitialiseWinFiles(void)\r
-{\r
- int i;\r
- \r
- RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));\r
-\r
- InitializeCriticalSection(&winFileLock);\r
-\r
- yfsd_LockWinFiles();\r
- for(i = 0; i < MAX_WIN_FILE; i++)\r
- {\r
- yfsd_winFile[i].isopen = 0;\r
- }\r
- yfsd_UnlockWinFiles();\r
-}\r
-\r
-yfsd_WinFile * yfsd_GetWinFile(void)\r
-{\r
- int i;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));\r
-\r
- yfsd_LockWinFiles();\r
-\r
- for(i = 0; i < MAX_WIN_FILE; i++)\r
- {\r
- if(!yfsd_winFile[i].isopen)\r
- {\r
- yfsd_winFile[i].isopen = 1;\r
- yfsd_winFile[i].writePermitted = 0;\r
- yfsd_winFile[i].readPermitted = 0;\r
- yfsd_winFile[i].shareRead = 0;\r
- yfsd_winFile[i].shareWrite = 0;\r
- yfsd_winFile[i].dirty = 0;\r
- yfsd_winFile[i].fullName = NULL;\r
- yfsd_winFile[i].obj = NULL;\r
-\r
- yfsd_UnlockWinFiles();\r
- return &yfsd_winFile[i];\r
- }\r
- }\r
-\r
- yfsd_UnlockWinFiles();\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));\r
-\r
- return NULL;\r
-}\r
-\r
-void yfsd_PutWinFile(yfsd_WinFile *f)\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));\r
- yfsd_LockWinFiles();\r
- f->isopen = 0;\r
- f->obj = NULL;\r
- if(f->fullName)\r
- {\r
- free(f->fullName);\r
- f->fullName = NULL;\r
- }\r
-\r
- yfsd_UnlockWinFiles();\r
-}\r
-\r
-\r
-\r
-void yfsd_FlushAllFiles(void)\r
-{\r
- int i;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));\r
-\r
- yfsd_LockYAFFS();\r
- yfsd_LockWinFiles();\r
- for(i = 0; i < MAX_WIN_FILE; i++)\r
- {\r
- if(yfsd_winFile[i].isopen &&\r
- yfsd_winFile[i].obj)\r
- {\r
- yaffs_FlushFile(yfsd_winFile[i].obj,1);\r
- }\r
- }\r
- yfsd_UnlockWinFiles();\r
- yfsd_UnlockYAFFS();\r
-}\r
-\r
-//slf021104d begin\r
-//////////////////////////////////////////////////////////////////////\r
-// Search through winFiles to see if any are open. \r
-\r
-BOOL yfsd_FilesOpen(void)\r
-{\r
- int i;\r
- BOOL rval;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));\r
-\r
- yfsd_LockWinFiles();\r
- for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)\r
- {\r
- if(yfsd_winFile[i].isopen)\r
- {\r
- rval = TRUE;\r
- break;\r
- }\r
- }\r
- yfsd_UnlockWinFiles();\r
- return rval;\r
-}\r
-//slf021104d end\r
-\r
-PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)\r
-{\r
-\r
- // todo check for bounds\r
- //slf021104b begin\r
- //volName already has the initial backslash if it needs it.\r
- //wcscpy(fpn,L"\\");\r
- //wcscat(fpn,vol->volName);\r
- wcscpy(fpn,vol->volName);\r
- //slf021104b end\r
- if(pathName[0] != '\\')\r
- {\r
- wcscat(fpn,L"\\");\r
- }\r
- wcscat(fpn,pathName);\r
-\r
- return fpn;\r
-\r
-}\r
-\r
-\r
-// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.\r
-\r
-void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)\r
-{\r
- \r
- wft->dwLowDateTime = target[0];\r
- wft->dwHighDateTime = target[1];\r
-\r
-}\r
-\r
-void yfsd_NullWinFileTime(FILETIME *wft)\r
-{\r
- wft->dwLowDateTime = 0;\r
- wft->dwHighDateTime = 0;\r
-}\r
-\r
-void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])\r
-{\r
- target[0] = wft->dwLowDateTime;\r
- target[1] = wft->dwHighDateTime;\r
-}\r
-\r
-void yfsd_WinFileTimeNow(__u32 target[2])\r
-{\r
- SYSTEMTIME st;\r
- FILETIME ft;\r
-\r
- GetSystemTime(&st);\r
- SystemTimeToFileTime(&st,&ft);\r
- yfsd_WinFileTimeToU32s(&ft,target);\r
-}\r
-\r
-// Cut down the name to the parent directory, then inform the shell of\r
-// a change to the directory.\r
-void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)\r
-{\r
- WCHAR str[500];\r
- int i;\r
- wcscpy(str,fullPathName);\r
-\r
- i = wcslen(str) - 1;\r
- \r
- if(i > 0)\r
- {\r
- str[i] = 0;\r
- i--;\r
- }\r
-\r
- // Curveball if the name is a directory (ie. we're doing an update of\r
- // a directory because we added a directory item). , then it might end in a \\r
- // which we must toss first\r
- if(i >= 0 && (str[i] == '\\' || str[i] == '/'))\r
- {\r
- str[i] = 0;\r
- i--;\r
- }\r
-\r
- // Ok, now strip back...\r
-\r
- while(i >= 0 && str[i] != '\\' && str[i] != '/')\r
- {\r
- str[i] = 0;\r
- i--;\r
- }\r
-\r
- if(pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- \r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_UPDATEDIR;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)str;\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = 0;\r
- yfsd_NullWinFileTime(&fc.ftModified);\r
- fc.nFileSize = 0;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));\r
-\r
- }\r
-\r
-\r
-}\r
-\r
-\r
-// Minimal name test for now\r
-BOOL yfsd_NameIsValid (const char *name)\r
-{\r
- int length = strlen(name);\r
-\r
- return (length > 0 && length <= YFSD_NAME_LENGTH);\r
-\r
-}\r
-\r
-// File attributes:\r
-// Wince understands the following attributes of any use to YAFFS:\r
-// \r
-// ARCHIVE\r
-// HIDDEN\r
-// READONLY\r
-// SYSTEM\r
-// TEMPORARY\r
-//\r
-// Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.\r
-//\r
-// It also understands NORMAL. If no other flag is set, then set NORMAL.\r
-// If any of the above are set, then NORMAL must **not** be set.\r
-// Ignore this and the WinCE Explorer barfs the file.\r
-//\r
-//\r
-// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY\r
-\r
-// The following are valid ones we get presented with,\r
-// but must filter out the stuff we don't unserstand\r
-//#define FILE_ATTRIBUTE_READONLY 0x00000001 \r
-//#define FILE_ATTRIBUTE_HIDDEN 0x00000002 \r
-//#define FILE_ATTRIBUTE_SYSTEM 0x00000004 \r
-//#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 \r
-//#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 \r
-//#define FILE_ATTRIBUTE_INROM 0x00000040\r
-//#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040 \r
-//#define FILE_ATTRIBUTE_NORMAL 0x00000080 \r
-//#define FILE_ATTRIBUTE_TEMPORARY 0x00000100 \r
-//#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 \r
-//#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 \r
-//#define FILE_ATTRIBUTE_COMPRESSED 0x00000800 \r
-//#define FILE_ATTRIBUTE_OFFLINE 0x00001000 \r
-//#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000\r
-//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 \r
-//#define FILE_ATTRIBUTE_ROMMODULE 0x00002000\r
-\r
-\r
-BOOL yfsd_CheckValidAttributes(DWORD attribs)\r
-{\r
-\r
- RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));\r
-\r
-#if 0\r
- // If NORMAL, then nothing else\r
- if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)\r
- return FALSE;\r
- if(attribs == FILE_ATTRIBUTE_NORMAL) \r
- return TRUE;\r
-#endif\r
- // Check that the bits are in the valid set\r
- if(attribs & ~(0x3FE7))\r
- return FALSE;\r
-\r
- return TRUE;\r
-\r
-}\r
-DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)\r
-{\r
-\r
- DWORD result;\r
- \r
- result = obj->st_mode & \r
- (FILE_ATTRIBUTE_READONLY | \r
- FILE_ATTRIBUTE_ARCHIVE | \r
- FILE_ATTRIBUTE_HIDDEN |\r
- FILE_ATTRIBUTE_SYSTEM);\r
-\r
- if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;\r
-\r
- if(result & ~FILE_ATTRIBUTE_NORMAL)\r
- { \r
- result &= ~FILE_ATTRIBUTE_NORMAL;\r
- }\r
- else \r
- {\r
- result = FILE_ATTRIBUTE_NORMAL;\r
- }\r
-\r
-\r
- return result;\r
-}\r
-\r
-\r
-\r
-/*\r
-* Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is\r
-* reached. Characters are copied from input into output until the above stop\r
-* condition is reached - output is then given a '\0'. output must be at least\r
-* as large as outSize\r
-*/\r
-static int parseToNextSlash(const unsigned short *input, char *output, int outSize)\r
-{\r
- int counter = 0;\r
- char *t = output;\r
- /* strip any starting \'s */\r
- //RETAILMSG(1, (L"\r\nParsing.. "));\r
- while (*input == '\\' || *input == '/') input++, counter++;\r
-\r
- for (; counter < outSize - 1; counter++)\r
- {\r
- if (*input == '\0' ||\r
- ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'\r
- {\r
- counter = -1; // break & tell people we've run to the end\r
- break;\r
- }\r
- if (*input == '\\' || *input == '/')\r
- break;\r
- //RETAILMSG(1, (L"%c", *input));\r
- *output = (char) (*input);\r
- input++;\r
- output++;\r
- }\r
- *output++ = '\0';\r
- *output = '\0';\r
-// RETAILMSG(1, (L"\r\nOut %a\r\n", t));\r
- \r
- return counter;\r
-}\r
-\r
-/*\r
-* Since the notion of paths as WinCE sees them and as YAFFS sees them\r
-* is different, we needed a helper function to search from the root of\r
-* device along the string in path. The processed pointer is set to where\r
-* abouts in the string the function was able to search up to.\r
-*/\r
-yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)\r
-{\r
- // a buffer to keep the current chunk of path we're talking about it\r
- char pathChunk[255];\r
- int chunkSize;\r
- int counter;\r
- // the current object we are at\r
- yaffs_Object *current;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));\r
- // start at the root of this device\r
- current = yaffs_Root(device);\r
- *processed = '\0';\r
-\r
- do\r
- {\r
- // parse chunks until we run out\r
- chunkSize = parseToNextSlash(path, pathChunk, 255);\r
-// RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));\r
- if (chunkSize == -1)\r
- break;\r
- // move the path pointer along\r
- path += chunkSize;\r
- // try and find the next yaffs object by chunkname \r
- current = yaffs_FindObjectByName(current, pathChunk);\r
- if (current == 0)\r
- {\r
- processed[0] = '\0';\r
- return 0;\r
- }\r
- } while (1);\r
-\r
- for (counter = 0; counter < length; counter++)\r
- {\r
- // Get the rest of the string\r
- processed[counter] = pathChunk[counter];\r
- if (pathChunk[counter] == '\0')\r
- break;\r
- }\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));\r
-\r
- return current;\r
-}\r
-\r
-\r
-yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )\r
-{\r
- yaffs_Object *obj = NULL;\r
- yaffs_Object *parent = NULL;\r
- char name[YFSD_NAME_LENGTH+1];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));\r
-\r
- parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
- if(parent && yfsd_NameIsValid(name))\r
- {\r
- obj = yaffs_FindObjectByName(parent,name);\r
- }\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));\r
-\r
- return obj;\r
-}\r
-\r
-BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)\r
-{\r
- //slf021104b Begin\r
- WCHAR szName[MAX_PATH];\r
- DWORD dwAvail;\r
- //slf021104b end\r
- RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));\r
- //slf021104b Begin filled in later.\r
- //vol->volName = volName;\r
- //slf021104b end\r
-\r
-\r
- yfsd_LockYAFFS();\r
- \r
- //slf021220a Begin Cleanup block driver interface\r
-#if _WINCEOSVER >= 400\r
- // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.\r
- vol->dev.genericDevice = (PVOID)hdsk;\r
-#endif\r
- //slf021220a End Cleanup block driver interface\r
-\r
- //Mount/initialise YAFFs here\r
- //slf021127a begin check for error returns!\r
- if (ynandif_InitialiseNAND(&vol->dev)) \r
- {\r
- //slf021127a end check for error returns!\r
- vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;\r
- vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;\r
- vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;\r
- vol->dev.initialiseNAND = ynandif_InitialiseNAND;\r
- vol->dev.startBlock = startBlock;\r
- if (endBlock != -1)\r
- vol->dev.endBlock = endBlock;\r
- vol->dev.nShortOpCaches = 10; // a nice number of caches.\r
- vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;\r
- vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;\r
-\r
-\r
- // nBlocks is set the total size of the disk, not the partition\r
- // vol->dev.nBlocks = endBlock - startBlock + 1;\r
-\r
- // qnand_EraseAllBlocks(&vol->dev);\r
-\r
- //slf021127a begin check for error returns!\r
- if (yaffs_GutsInitialise(&vol->dev))\r
- {\r
- //slf021127a end check for error returns!\r
- RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));\r
-\r
- RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",\r
- vol->dev.startBlock,vol->dev.endBlock,\r
- vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));\r
-\r
-\r
-#if 0\r
- for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)\r
- {\r
- switch(vol->dev.blockInfo[i].blockState)\r
- {\r
- case YAFFS_BLOCK_STATE_DEAD:\r
- \r
- RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));\r
- deadBlox++;\r
- break;\r
- case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;\r
- case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;\r
- case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;\r
- case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;\r
- default:\r
- RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));\r
- break;\r
- }\r
- }\r
-\r
- RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",\r
- deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));\r
-\r
-#endif\r
-\r
-//slf021127a begin check for error returns!\r
- vol->isMounted = 1;\r
- }\r
- }\r
-//slf021127a begin check for error returns!\r
- \r
- yfsd_UnlockYAFFS();\r
-\r
-//slf021127a begin check for error returns!\r
-// vol->isMounted = 1;\r
-//slf021127a begin check for error returns!\r
- \r
- //slf021104b begin\r
- //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);\r
- // If the caller passed a volume name use it.\r
- if (volName[0])\r
- wcscpy( szName, volName);\r
-#if WINCEOSVER >= 400\r
- // The user passed an empty volume name. On CE 4.xx try to get\r
- // if from the block driver (which got it from the registry).\r
- else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL)) \r
-#else\r
- else\r
-#endif\r
- { \r
- // Didn't get a volume name so use "Disk" by default.\r
- wcscpy( szName, YFSD_DISK_NAME);\r
- } \r
- vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);\r
- //slf021104b end\r
-\r
- if(vol->mgrVolume)\r
- {\r
- //slf021104b Begin\r
- // Get some space for the volume name.\r
- vol->volName = malloc( MAX_PATH * sizeof(WCHAR));\r
- if (vol->volName) \r
- {\r
-#if WINCEOSVER >= 400\r
- // Get the name we were really mounted under.\r
- FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);\r
-\r
- // If we got mounted as root then throw away the backslash\r
- // so we won't get a double backslash when volName is\r
- // prepended to the path in the full path name calculation\r
- // that is used for shell callbacks.\r
- if (0 == wcscmp(vol->volName,L"\\"))\r
- vol->volName[0] = 0;\r
-#else\r
- // Use the name we asked to be mounted under for\r
- // our root. \r
- wcscpy(vol->volName,L"\\");\r
- wcscat(vol->volName, szName);\r
-#endif\r
- }\r
- //slf021104b end\r
- return TRUE;\r
- }\r
- else\r
- {\r
- vol->isMounted = 0;\r
- SetLastError(ERROR_OUTOFMEMORY);\r
- return FALSE;\r
- } \r
-}\r
-\r
-\r
-BOOL YFSD_MountDisk(HDSK hdsk)\r
-{\r
-//slf021105a begin\r
-#ifdef DO_PARTITION_TABLE\r
- ynandif_partition PartTable[MAXPARTITIONS];\r
- DWORD dwAvail;\r
- int i;\r
- BOOL rval = FALSE;\r
-#endif\r
-//slf021105a end\r
- int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;\r
- //int i;\r
- // Called to mount a disk.\r
- // NB THis call might happen redundantly.\r
- //\r
- //\r
- // If yaffs is not initialised, then call the \r
- // initialisation function\r
- //\r
- RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));\r
-\r
- if (!yaffsLockInited)\r
- {\r
- InitializeCriticalSection(&yaffsLock);\r
- yfsd_InitialiseWinFiles();\r
- yaffsLockInited = 1;\r
- }\r
-\r
- //slf021105a begin\r
- memset(disk_volumes,0,sizeof(disk_volumes));\r
-#ifdef DO_PARTITION_TABLE\r
- memset(&PartTable,0,sizeof(PartTable));\r
- // Call the block driver to get the partition table from it.\r
- if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL)) \r
- {\r
- // Scan throught the table it return.\r
- for (i=0; i<MAXPARTITIONS; i++)\r
- {\r
- // At the very lease check that the end is later than the beginning\r
- // and don't let it start at 0. \r
- // Probably could do more thorough checking but I trust the block\r
- // driver.\r
- if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))\r
- {\r
- // Found a partion. Get a volume structure to hold it.\r
- disk_volumes[i] = malloc(sizeof(yfsd_Volume));\r
- if (disk_volumes[i])\r
- {\r
- memset(disk_volumes[i],0,sizeof(yfsd_Volume));\r
- // Go init the volume. Note that if the block driver wants the\r
- // name to come from the registry it will have returned an\r
- // empty name string.\r
- YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);\r
- if (disk_volumes[i]->isMounted)\r
- rval = TRUE; //Hey, we found at least on partition.\r
- }\r
- }\r
- }\r
- }\r
-\r
- return rval;\r
-\r
-#else\r
-#ifdef DISABLE_BOOT_PARTITION\r
- // Only want disk volume\r
- disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
- if (disk_volumes[0])\r
- {\r
- memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
- YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);\r
-\r
- if(disk_volumes[0].isMounted)\r
- {\r
- return TRUE;\r
- }\r
- }\r
- if (disk_volumes[0])\r
- {\r
- free(disk_volumes[0];\r
- disk_volumes[0] = NULL;\r
- }\r
-#else\r
- // Want both boot and disk\r
- disk_volumes[0] = malloc(sizeof(yfsd_Volume));\r
- disk_volumes[1] = malloc(sizeof(yfsd_Volume));\r
- if (disk_volumes[0] && disk_volumes[1])\r
- {\r
- memset(disk_volumes[0],0,sizeof(yfsd_Volume));\r
- memset(disk_volumes[1],0,sizeof(yfsd_Volume));\r
- YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);\r
- YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);\r
-\r
-#ifdef MSGBOX_DISPLAY\r
- // pass the device we are sniffing to the thread\r
- CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);\r
-#endif\r
-\r
- if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)\r
- {\r
- return TRUE;\r
- }\r
- }\r
-\r
- // If we got this far something went wrong. Make sure to \r
- // free any memory we allocated.\r
- if (disk_volumes[0])\r
- {\r
- if (disk_volumes[0]->volName)\r
- {\r
- free(disk_volumes[0]->volName);\r
- }\r
- free(disk_volumes[0]);\r
- disk_volumes[0] = NULL;\r
- }\r
- if (disk_volumes[1])\r
- {\r
- if (disk_volumes[1]->volName)\r
- {\r
- free(disk_volumes[1]->volName);\r
- }\r
- free(disk_volumes[1]);\r
- disk_volumes[1] = NULL;\r
- }\r
-#endif\r
-\r
- return FALSE;\r
-\r
- // Only want disk volume\r
-// YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);\r
-//\r
-// \r
-// if(disk_volume.isMounted)\r
-// {\r
-// return TRUE;\r
-// }\r
-//#else\r
-// // Want both boot and disk\r
-// YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);\r
-// YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);\r
-//\r
-// \r
-// if(disk_volume.isMounted && boot_volume.isMounted)\r
-// {\r
-// return TRUE;\r
-// }\r
-//#endif\r
-//\r
-// return FALSE;\r
-#endif\r
-//slf021105a end\r
-\r
-// yfsd_SetGuards();\r
-\r
- // todo - get name from registry\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_UnmountDisk(HDSK hdsk)\r
-{\r
-//slf021105a begin\r
- int i;\r
-//slf021105a end\r
- RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));\r
- \r
- //slf021104d begin\r
- // If there are any files open don't let them dismount\r
- // it or the system will get very confused. \r
- if (yfsd_FilesOpen())\r
- return FALSE;\r
-\r
- //yfsd_FlushAllFiles();\r
- //slf021104d end\r
-\r
- yfsd_LockYAFFS();\r
-//slf021105a begin\r
-// yaffs_Deinitialise(&disk_volume.dev);\r
-// yaffs_Deinitialise(&boot_volume.dev);\r
-// yfsd_UnlockYAFFS();\r
-//\r
-// FSDMGR_DeregisterVolume(disk_volume.mgrVolume);\r
-// FSDMGR_DeregisterVolume(boot_volume.mgrVolume);\r
-\r
- // Walk through the partions deinitializing, deregistering\r
- // and freeing them.\r
- for (i=0; i<MAXPARTITIONS; i++)\r
- {\r
- if (disk_volumes[i])\r
- {\r
- yaffs_Deinitialise(&(disk_volumes[i]->dev));\r
-//slf021220a Begin Cleanup block driver interface\r
- ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));\r
-//slf021220a end Cleanup block driver interface\r
- FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);\r
- if (disk_volumes[i]->volName)\r
- {\r
- free(disk_volumes[i]->volName);\r
- }\r
- free(disk_volumes[i]);\r
- disk_volumes[i] = NULL;\r
- }\r
- }\r
- yfsd_UnlockYAFFS();\r
-//slf021105a end\r
- return TRUE;\r
-}\r
-\r
-\r
-BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)\r
-{\r
- // security attributes are ignored (should be NULL)\r
-\r
- yaffs_Object *newDir = NULL;\r
- yaffs_Object *parent = NULL;\r
- char name[YFSD_NAME_LENGTH+1];\r
- ULONG objSize;\r
- DWORD attribs;\r
- unsigned modifiedTime[2];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));\r
-\r
- yfsd_LockYAFFS();\r
-\r
- parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);\r
-\r
- //slf021101b begin \r
- if (parent)\r
- {\r
- if(yfsd_NameIsValid(name))\r
- {\r
- newDir = yaffs_MknodDirectory(parent,name,0,0,0);\r
- if(newDir)\r
- {\r
- objSize = yaffs_GetObjectFileLength(newDir);\r
- attribs = yfsd_GetObjectWinAttributes(newDir);\r
- modifiedTime[0] = newDir->win_mtime[0];\r
- modifiedTime[1] = newDir->win_mtime[1];\r
- }\r
- else\r
- {\r
- if(yaffs_FindObjectByName(parent,name))\r
- SetLastError(ERROR_ALREADY_EXISTS);\r
- else\r
- SetLastError(ERROR_DISK_FULL);\r
- }\r
- }\r
- else\r
- SetLastError(ERROR_INVALID_NAME);\r
- }\r
- else\r
- {\r
- SetLastError(ERROR_PATH_NOT_FOUND);\r
- }\r
- //slf021101b end\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- // Call shell function to tell of new directory\r
- if(newDir && pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_MKDIR;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs; \r
- yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- //yfsd_ShellDirectoryChanged(pVolume,fpn);\r
-\r
- }\r
-\r
-//slf021101b begin \r
-// if(parent && !newDir)\r
-// {\r
-// SetLastError(ERROR_DISK_FULL);\r
-// }\r
-//slf021101b end\r
-\r
- return newDir ? TRUE : FALSE;\r
-}\r
-\r
-\r
-BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)\r
-{\r
- int result = FALSE;\r
- yaffs_Object *parent = NULL;\r
- yaffs_Object *obj;\r
- char name[YFSD_NAME_LENGTH+1];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));\r
- \r
- yfsd_LockYAFFS();\r
-\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);\r
- if(!obj)\r
- {\r
- SetLastError(ERROR_PATH_NOT_FOUND);\r
- result = FALSE;\r
- }\r
- else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else if(obj->inUse)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else\r
- {\r
-\r
- parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);\r
-\r
- if(parent && yfsd_NameIsValid(name))\r
- {\r
- result = yaffs_Unlink(parent,name);\r
- if(!result)\r
- SetLastError(ERROR_DIR_NOT_EMPTY);\r
- }\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- if(result && pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_RMDIR;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = 0;\r
- yfsd_NullWinFileTime(&fc.ftModified);\r
- fc.nFileSize = 0;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- yfsd_ShellDirectoryChanged(pVolume,fpn);\r
- }\r
- \r
- return result ? TRUE : FALSE;\r
-}\r
-\r
-\r
-DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )\r
-{\r
- yaffs_Object *obj = NULL;\r
-\r
- DWORD result = 0xFFFFFFFF;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));\r
-\r
- yfsd_LockYAFFS();\r
-\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-\r
- if(obj)\r
- {\r
- result = yfsd_GetObjectWinAttributes(obj);\r
- }\r
- else\r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
- \r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));\r
- return result;\r
-\r
- \r
-}\r
-\r
-BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )\r
-{\r
- yaffs_Object *obj = NULL;\r
- DWORD mtime[2];\r
- DWORD attribs;\r
- DWORD objSize;\r
-\r
- int result = 0;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));\r
-\r
- if(!yfsd_CheckValidAttributes(dwFileAttributes))\r
- {\r
- SetLastError(ERROR_INVALID_PARAMETER);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
-\r
- if(obj)\r
- {\r
- obj->st_mode = dwFileAttributes;\r
- obj->dirty = 1;\r
- result = yaffs_FlushFile(obj,0);\r
- attribs = yfsd_GetObjectWinAttributes(obj);\r
- objSize = yaffs_GetObjectFileLength(obj);\r
- mtime[0] = obj->win_mtime[0];\r
- mtime[1] = obj->win_mtime[1];\r
- }\r
- else\r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- if(result && pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_ATTRIBUTES;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- //yfsd_ShellDirectoryChanged(pVolume,fpn);\r
- }\r
- \r
-\r
- return result;\r
-\r
-}\r
-\r
-BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )\r
-{\r
- int result = FALSE;\r
- yaffs_Object *parent = NULL;\r
- yaffs_Object *obj;\r
- char name[YFSD_NAME_LENGTH+1];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));\r
-\r
- yfsd_LockYAFFS();\r
-\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- if(!obj)\r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- result = FALSE;\r
- }\r
- else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else if(obj->inUse)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- result = FALSE;\r
- }\r
- else\r
- {\r
-\r
- parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
- if(parent && yfsd_NameIsValid(name))\r
- {\r
- result = yaffs_Unlink(parent,name);\r
- if(!result)\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- }\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- if(result && pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_DELETE;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = -1;\r
- yfsd_NullWinFileTime(&fc.ftModified);\r
- fc.nFileSize = 0;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- yfsd_ShellDirectoryChanged(pVolume,fpn);\r
- }\r
-\r
- return result ? TRUE : FALSE;\r
-}\r
-\r
-BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )\r
-{\r
- yaffs_Object *newParent = NULL;\r
- yaffs_Object *oldParent = NULL;\r
- yaffs_Object *obj = NULL;\r
- char oldName[YFSD_NAME_LENGTH+1];\r
- char newName[YFSD_NAME_LENGTH+1];\r
- int result = 0;\r
- int objIsDir = 0;\r
- DWORD attribs;\r
- DWORD objSize;\r
- DWORD mtime[2];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));\r
-\r
- yfsd_LockYAFFS();\r
-\r
- oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);\r
- newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);\r
-\r
- if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))\r
- {\r
- result = yaffs_RenameObject(oldParent,oldName,newParent,newName);\r
- if(!result)\r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- }\r
-\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);\r
- if(obj)\r
- {\r
- objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);\r
- attribs = yfsd_GetObjectWinAttributes(obj);\r
- objSize = yaffs_GetObjectFileLength(obj);\r
- mtime[0] = obj->win_mtime[0];\r
- mtime[1] = obj->win_mtime[1];\r
- }\r
- }\r
- else\r
- {\r
- SetLastError(ERROR_PATH_NOT_FOUND);\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
-\r
- if(result && pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];\r
- WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);\r
- fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- yfsd_ShellDirectoryChanged(pVolume,fpn1);\r
- yfsd_ShellDirectoryChanged(pVolume,fpn2);\r
- }\r
-\r
-\r
- return result ? TRUE : FALSE;\r
-\r
-}\r
-\r
-BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )\r
-{\r
- //slf021104c begin\r
- BOOL fSuccess;\r
- //slf021104c end\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));\r
-\r
- //slf021104c begin\r
- if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))\r
- fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);\r
- return fSuccess;\r
- //return FALSE;\r
- //slf021104c end\r
-}\r
-\r
-BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )\r
-{\r
-\r
- int nChunks;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));\r
-\r
- yfsd_LockYAFFS();\r
- nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);\r
- yfsd_UnlockYAFFS();\r
-\r
- if(nChunks >= 0)\r
- {\r
- // Let's pretentd our clusters are the same size as eraseable blocks...\r
- *pBytesPerSector = 512;\r
- *pSectorsPerCluster =32;\r
- *pFreeClusters = nChunks/32;\r
- *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;\r
- }\r
-\r
- return (nChunks >= 0)? TRUE : FALSE;\r
-\r
-\r
-\r
-}\r
-\r
-void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )\r
-{\r
- // Flags can be one of:\r
- // FSNOTIFY_POWER_ON: no action required\r
- // FSNOTIFY_POWER_OFF: flush all files\r
- // FSNOTIFY_DEVICE_ON: no action required\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));\r
- if(dwFlags == FSNOTIFY_POWER_OFF)\r
- {\r
- yfsd_FlushAllFiles();\r
- }\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));\r
- \r
- pVolume->shellFunction = pfn;\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-int iMatch(const char a, const char b)\r
-{\r
- if (a == '?' || b == '?')\r
- return 1;\r
- return (toupper(a) == toupper(b));\r
-}\r
-\r
-void pString(const char *inp)\r
-{\r
- while (*inp) RETAILMSG(1, (L"%c", *inp++));\r
-}\r
-\r
-int regularMatch(const char *regexp, const char *str)\r
-{\r
-// pString(regexp);\r
-// RETAILMSG(1, (L" "));\r
-// pString(str);\r
-// RETAILMSG(1, (L"\r\n"));\r
-\r
- if (*regexp == 0 && *str == 0)\r
- {\r
- //RETAILMSG(1, (L"Match!\r\n"));\r
- return 1;\r
- }\r
- if (*regexp == '*') \r
- {\r
- regexp++;\r
- if (*regexp == 0) // end of the expression is a *, we must match\r
- {\r
- //RETAILMSG(1, (L"Match!\r\n"));\r
- return 1;\r
- }\r
- while (!iMatch(*regexp, *str)) // throw away chars from str until we match\r
- {\r
- if (*str == 0) // if we're not at the end\r
- {\r
- // if we have .* left to match, but the str is finished then match it OK\r
- if (regexp[0] == '.' && regexp[1] == '*')\r
- {\r
- //RETAILMSG(1, (L"Match!\r\n"));\r
- return 1;\r
- }\r
- else\r
- {\r
- // the extension failed the match\r
- //RETAILMSG(1, (L"No Match!\r\n"));\r
- return 0;\r
- }\r
- }\r
- str++;\r
- } \r
- // right now we should either eat more characters, or try to match\r
- return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));\r
- }\r
-// compare chars until we hit another *, or we fail\r
- while (iMatch(*regexp, *str))\r
- {\r
- if (*regexp == 0 && *str == 0)\r
- {\r
- //RETAILMSG(1, (L"Match!\r\n"));\r
- return 1;\r
- }\r
- regexp++;\r
- str++;\r
- }\r
-\r
- if (*regexp == 0 && *str == 0)\r
- {\r
- //RETAILMSG(1, (L"Match!\r\n"));\r
- return 1;\r
- }\r
-\r
- if (*regexp == '*')\r
- return regularMatch(regexp, str);\r
-\r
- //RETAILMSG(1, (L"No Match!\r\n"));\r
- return 0;\r
-}\r
-\r
-\r
-void yfsd_DeleteFinder(PSEARCH pSearch)\r
-{\r
- if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.\r
- {\r
- yaffs_FoundObject *it;\r
- yaffs_FoundObject *temp;\r
-\r
- it = pSearch->foundObjects;\r
-\r
- while(it != NULL)\r
- {\r
- temp = it;\r
- it = it->next;\r
- \r
- free(temp);\r
- }\r
-\r
- pSearch->foundObjects = NULL;\r
- }\r
-\r
- pSearch->dir->inUse--;\r
- free(pSearch);\r
-}\r
-\r
-BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)\r
-{\r
- //Iterate through the current list of objs already found and return true if already exists.\r
- //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.\r
- BOOL found = FALSE;\r
-\r
- yaffs_FoundObject *it;\r
- it = pSearch->foundObjects;\r
-\r
- \r
- while(it->next != NULL) //iterate through singly linked list.\r
- {\r
- if(it->obj == l)\r
- {\r
- found = TRUE;\r
- break;\r
- }\r
- it = it->next;\r
- }\r
-\r
- if(!found)\r
- {\r
- //Add the item to the list.\r
- //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL\r
- it->next = malloc(sizeof(yaffs_FoundObject));\r
- it->next->next = NULL;\r
- it->next->obj = 0;\r
-\r
- it->obj = l;\r
- }\r
-\r
- return found;\r
-}\r
-\r
-#if 0\r
-// slower one\r
-BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)\r
-{\r
-\r
- struct list_head *i;\r
- int pos;\r
- yaffs_Object *l;\r
- BOOL found = 0;\r
-\r
- char name[YAFFS_MAX_NAME_LENGTH+1];\r
-\r
- if(!pSearch->foundObjects)\r
- {\r
- pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));\r
- pSearch->foundObjects->next = NULL;\r
- pSearch->foundObjects->obj = 0;\r
- }\r
-\r
-\r
- yfsd_LockYAFFS();\r
-\r
- pos = 0;\r
- list_for_each(i,&pSearch->dir->variant.directoryVariant.children)\r
- {\r
-\r
- l = list_entry(i, yaffs_Object,siblings);\r
-\r
- yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);\r
-\r
- if(regularMatch(pSearch->pattern,name))\r
- {\r
- if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)\r
- { \r
-\r
- \r
- found = 1;\r
- //pSearch->currentPos++;\r
-\r
- // fill out find data\r
-\r
- pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);\r
-\r
- yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);\r
- yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);\r
- yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);\r
-\r
- pfd->nFileSizeHigh = 0;\r
- pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);\r
- pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???\r
-\r
- MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);\r
-\r
- RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",\r
- pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,\r
- l->variant.fileVariant.scannedFileSize));\r
- goto out_of_here;\r
- }\r
- else\r
- {\r
- pos++;\r
- }\r
- }\r
- }\r
-\r
-out_of_here:\r
- yfsd_UnlockYAFFS();\r
-\r
-\r
- if(!found)\r
- {\r
- SetLastError(ERROR_NO_MORE_FILES);\r
- }\r
- return found;\r
- \r
-}\r
-\r
-#else\r
-// faster one\r
-BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)\r
-{\r
-\r
- struct list_head *i;\r
- yaffs_Object *l;\r
- BOOL found = 0;\r
-\r
- char name[YAFFS_MAX_NAME_LENGTH+1];\r
-\r
- if(!pSearch->foundObjects)\r
- {\r
- pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));\r
- pSearch->foundObjects->next = NULL;\r
- pSearch->foundObjects->obj = 0;\r
- }\r
-\r
-\r
- yfsd_LockYAFFS();\r
-\r
- list_for_each(i,&pSearch->dir->variant.directoryVariant.children)\r
- {\r
-\r
- l = list_entry(i, yaffs_Object,siblings);\r
- if(!yfsd_ObjectAlreadyFound(pSearch,l))\r
- {\r
- // Only look at things we have not looked at already\r
- yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);\r
-\r
- if(regularMatch(pSearch->pattern,name))\r
- {\r
- found = 1;\r
- // fill out find data\r
-\r
- pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);\r
-\r
- yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);\r
- yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);\r
- yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);\r
-\r
- pfd->nFileSizeHigh = 0;\r
- pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);\r
- pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???\r
-\r
- MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);\r
-\r
- RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",\r
- pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,\r
- l->variant.fileVariant.scannedFileSize));\r
- goto out_of_here;\r
- }\r
-\r
- }\r
-\r
-\r
- }\r
-\r
-out_of_here:\r
- yfsd_UnlockYAFFS();\r
-\r
-\r
- if(!found)\r
- {\r
- SetLastError(ERROR_NO_MORE_FILES);\r
- }\r
- return found;\r
- \r
-}\r
-#endif\r
-\r
-HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )\r
-{\r
-\r
- // Create a search context, register it, and do the first search\r
-\r
- PSEARCH pSearch;\r
- HANDLE h = INVALID_HANDLE_VALUE;\r
- BOOL found = 0;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));\r
-\r
- pSearch = malloc(sizeof(yfsd_WinFind));\r
- if(!pSearch)\r
- {\r
- SetLastError(ERROR_OUTOFMEMORY);\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- if(pSearch)\r
- {\r
- pSearch->foundObjects = NULL; //pSearch->currentPos = 0;\r
- pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);\r
- if(pSearch->dir)\r
- {\r
- pSearch->dir->inUse++;\r
- }\r
- else\r
- {\r
- free(pSearch);\r
- pSearch = NULL;\r
- SetLastError(ERROR_PATH_NOT_FOUND);\r
- }\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
-\r
-\r
- if(pSearch)\r
- {\r
- found = yfsd_DoFindFile(pSearch,pfd);\r
-\r
- if(found)\r
- {\r
- h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);\r
- if(h == INVALID_HANDLE_VALUE)\r
- {\r
- SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);\r
- }\r
- }\r
- else\r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- }\r
-\r
- if(h == INVALID_HANDLE_VALUE)\r
- {\r
- yfsd_DeleteFinder(pSearch);\r
- }\r
-\r
- }\r
-\r
-\r
- return h;\r
-}\r
-\r
-BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));\r
- if(!pSearch)\r
- {\r
- return FALSE;\r
- }\r
- return yfsd_DoFindFile(pSearch,pfd);\r
-}\r
-\r
-BOOL YFSD_FindClose( PSEARCH pSearch )\r
-{ \r
- RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));\r
- if(!pSearch)\r
- {\r
- return FALSE;\r
- }\r
- yfsd_DeleteFinder(pSearch);\r
- return TRUE;\r
-}\r
-\r
-\r
-HANDLE YFSD_CreateFileW( \r
- PVOLUME pVolume, \r
- HANDLE hProc, \r
- PCWSTR pwsFileName, \r
- DWORD dwAccess, \r
- DWORD dwShareMode,\r
- PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore\r
- DWORD dwCreate,\r
- DWORD dwFlagsAndAttributes, \r
- HANDLE hTemplateFile ) // ignore\r
-{\r
-\r
-\r
- yaffs_Object *parent = NULL;\r
- yaffs_Object *obj = NULL;\r
- char name[YFSD_NAME_LENGTH+1];\r
- int mode;\r
- yfsd_WinFile *f = NULL;\r
- HANDLE handle = INVALID_HANDLE_VALUE;\r
- unsigned modifiedTime[2];\r
- unsigned objSize;\r
-\r
- BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;\r
- BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;\r
- BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;\r
- BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;\r
-\r
- BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;\r
-\r
- BOOL fileCreated = FALSE;\r
- \r
- BOOL fAlwaysCreateOnExistingFile = FALSE;\r
- BOOL fTruncateExistingFile = FALSE;\r
-\r
-\r
- mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));\r
- if(writePermitted)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));\r
- }\r
-\r
- if(!yfsd_CheckValidAttributes(mode))\r
- {\r
- SetLastError(ERROR_INVALID_PARAMETER);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
-\r
- parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);\r
-\r
-\r
- if(parent && yfsd_NameIsValid(name))\r
- {\r
-\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // Get the object for this file if it exists (only once).\r
- obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- if(dwCreate == CREATE_NEW)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));\r
-\r
- //slf021101c begin\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- if(!obj)\r
- {\r
- obj = yaffs_MknodFile(parent,name,mode,0,0);\r
- if(!obj)\r
- SetLastError(ERROR_DISK_FULL);\r
- fileCreated = TRUE;\r
- }\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
- {\r
- obj = NULL;\r
- SetLastError(ERROR_ALREADY_EXISTS);\r
- }\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- else\r
- {\r
- obj = NULL;\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);\r
- SetLastError(ERROR_FILE_EXISTS);\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- }\r
- //slf021101c end\r
- }\r
- else if( dwCreate == OPEN_ALWAYS)\r
- {\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- if(!obj)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));\r
- obj = yaffs_MknodFile(parent,name,mode,0,0);\r
- if(!obj)\r
- SetLastError(ERROR_DISK_FULL);\r
- fileCreated = TRUE;\r
-\r
- }\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
- {\r
- obj = NULL;\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- }\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));\r
- }\r
- }\r
- else if(dwCreate == OPEN_EXISTING)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- if(!obj)\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- //slf021101c begin\r
- // else\r
- // if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)\r
- // {\r
- // SetLastError(ERROR_ACCESS_DENIED);\r
- // obj = NULL;\r
- // }\r
- //slf021101c end\r
- else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
- {\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- obj = NULL;\r
- }\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- }\r
- else if(dwCreate == TRUNCATE_EXISTING)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //if(obj)\r
- if (!writePermitted || (obj && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))\r
- {\r
- obj = NULL;\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- }\r
- else if(obj)\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- {\r
- // Indicate that file is to be truncated. This will happen later on assuming\r
- // that a sharing violation does not occur and that we can get a file handle.\r
- fTruncateExistingFile = TRUE;\r
- }\r
- else \r
- {\r
- SetLastError(ERROR_FILE_NOT_FOUND);\r
- }\r
- }\r
- else if(dwCreate == CREATE_ALWAYS)\r
- {\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);\r
- //slf021220b end Fix still more bugs in CreateFile.\r
-\r
- if(!obj)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));\r
- obj = yaffs_MknodFile(parent,name,mode,0,0);\r
- if(!obj)\r
- SetLastError(ERROR_DISK_FULL);\r
- fileCreated = TRUE;\r
- }\r
- //slf021220b begin Fix still more bugs in CreateFile.\r
- else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)\r
- {\r
- obj = NULL;\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- }\r
- //slf021220b end Fix still more bugs in CreateFile.\r
- else\r
- { \r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));\r
- // Indicate that file is to be recreated. This will happen later on assuming\r
- // that a sharing violation does not occur and that we can get a file handle.\r
- fAlwaysCreateOnExistingFile = TRUE;\r
- }\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));\r
- SetLastError(ERROR_INVALID_PARAMETER);\r
- }\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));\r
- SetLastError(ERROR_PATH_NOT_FOUND);\r
- }\r
-\r
- if(obj)\r
- {\r
- int i;\r
- yfsd_WinFile *p;\r
- openRead = openWrite =0;\r
- openReadAllowed = openWriteAllowed = 1;\r
-\r
- for(i = 0; i < MAX_WIN_FILE; i++)\r
- {\r
- p = &yfsd_winFile[i];\r
-\r
- if(p->obj == obj)\r
- {\r
- if (p->readPermitted) openRead = 1;\r
- if (p->writePermitted) openWrite = 1;\r
- if (!p->shareRead) openReadAllowed = 0;\r
- if (!p->shareWrite) openWriteAllowed = 0;\r
- }\r
-\r
- }\r
-\r
- // Now we test if the share works out.\r
-\r
- if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read\r
- (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write\r
- (!openReadAllowed && readPermitted) || // already open with read sharing not permitted\r
- (!openWriteAllowed && writePermitted)) // same... write\r
- {\r
- //slf021220c begin Fix error code for new sharing mode check code.\r
- SetLastError(ERROR_SHARING_VIOLATION);\r
- //slf021220c end Fix error code for new sharing mode check code.\r
- obj = NULL;\r
- }\r
-\r
-\r
- }\r
- if(obj)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));\r
- f = yfsd_GetWinFile();\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));\r
- }\r
-\r
- if(f)\r
- {\r
-\r
- handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);\r
-\r
- if(handle != INVALID_HANDLE_VALUE)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));\r
-\r
- if (fTruncateExistingFile)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));\r
- yaffs_ResizeFile(obj,0);\r
- }\r
- \r
- if (fAlwaysCreateOnExistingFile)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));\r
- obj->st_mode = mode;\r
- obj->dirty = 1;\r
- yaffs_ResizeFile(obj,0);\r
- yaffs_FlushFile(obj,1);\r
- }\r
- \r
- f->obj = obj;\r
- f->offset = 0;\r
- f->writePermitted = writePermitted;\r
- //slf021220d begin oops typo.\r
- f->readPermitted = readPermitted;\r
- //slf021220d end oops typo.\r
- f->shareRead= shareRead;\r
- f->shareWrite = shareWrite;\r
- f->myVolume = pVolume;\r
- obj->inUse++;\r
-\r
- modifiedTime[0] = obj->win_mtime[0];\r
- modifiedTime[1] = obj->win_mtime[1];\r
- objSize = yaffs_GetObjectFileLength(obj);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));\r
- }\r
- else\r
- {\r
- yfsd_PutWinFile(f);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));\r
- }\r
-\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- if(handle != INVALID_HANDLE_VALUE && \r
- fileCreated &&\r
- pVolume->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
-\r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_CREATE;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = mode;\r
- yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- pVolume->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
-\r
- yfsd_ShellDirectoryChanged(pVolume,fpn);\r
- }\r
-\r
- if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))\r
- {\r
- // Remember the name\r
-\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
- int slen;\r
-\r
- yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);\r
- slen = wcslen(fpn);\r
- f->fullName = malloc((slen+1)* sizeof(WCHAR));\r
- if(f->fullName)\r
- {\r
- wcscpy(f->fullName,fpn);\r
- }\r
-\r
- }\r
-\r
-\r
- return handle;\r
-\r
-}\r
-\r
-BOOL yfsd_DoReadFile( \r
- PFILE pFile, \r
- PVOID pBuffer, \r
- DWORD cbRead, \r
- PDWORD pcbRead)\r
-{\r
- \r
- DWORD maxRead;\r
- int nread = 0;\r
- yaffs_Object *obj = NULL;\r
-\r
-\r
- if(pcbRead)\r
- {\r
- *pcbRead = 0;\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));\r
- }\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
- \r
- obj = pFile->obj;\r
-\r
- if(yaffs_GetObjectFileLength(obj) > pFile->offset)\r
- {\r
- maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;\r
- }\r
- else\r
- {\r
- maxRead = 0;\r
- }\r
-\r
- if(cbRead > maxRead)\r
- {\r
- cbRead = maxRead;\r
- }\r
- \r
- if(maxRead > 0)\r
- {\r
- nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);\r
- if(nread > 0)\r
- {\r
- pFile->offset += nread;\r
-\r
- if(pcbRead)\r
- {\r
- *pcbRead = nread;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- if(pcbRead) \r
- {\r
- *pcbRead = maxRead;\r
- }\r
- }\r
-\r
-\r
- return nread < 0? FALSE : TRUE; \r
-\r
-}\r
-\r
-BOOL YFSD_ReadFile( \r
- PFILE pFile, \r
- PVOID pBuffer, \r
- DWORD cbRead, \r
- PDWORD pcbRead, \r
- OVERLAPPED *pOverlapped ) //ignore\r
-{\r
- BOOL result;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return result;\r
-}\r
-\r
-BOOL YFSD_ReadFileWithSeek( \r
- PFILE pFile, \r
- PVOID pBuffer, \r
- DWORD cbRead, \r
- PDWORD pcbRead, \r
- OVERLAPPED *pOverlapped, \r
- DWORD dwLowOffset, \r
- DWORD dwHighOffset )\r
-{\r
- BOOL result;\r
- DWORD rememberedOffset;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));\r
-\r
- // To determine if paging is supported, the kernel calls this with all parameters except pFile\r
- // being zero.\r
- if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)\r
- {\r
- return TRUE; // paging suppported\r
- //return FALSE; // paging not supported\r
- }\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- rememberedOffset = pFile->offset;\r
-\r
- pFile->offset = dwLowOffset;\r
- // ignore high offset for now\r
-\r
- result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);\r
-\r
- //pFile->offset = rememberedOffset;\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return result;\r
-\r
-\r
-}\r
-\r
-\r
-BOOL yfsd_DoWriteFile( \r
- PFILE pFile, \r
- PCVOID pBuffer, \r
- DWORD cbWrite, \r
- PDWORD pcbWritten)\r
-{\r
- int nwritten = 0;\r
- yaffs_Object *obj = NULL;\r
- \r
- RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));\r
- \r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- if(!pFile->writePermitted)\r
- {\r
- *pcbWritten = 0;\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- return FALSE;\r
- }\r
-\r
- obj = pFile->obj;\r
-\r
- *pcbWritten = 0;\r
-\r
-\r
- nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);\r
- if(nwritten >= 0)\r
- {\r
- pFile->offset += nwritten;\r
- *pcbWritten = nwritten;\r
- }\r
- if(nwritten != cbWrite)\r
- {\r
- SetLastError(ERROR_DISK_FULL);\r
- }\r
-\r
-\r
- return nwritten != cbWrite? FALSE : TRUE; \r
-}\r
-\r
-\r
-BOOL YFSD_WriteFile( \r
- PFILE pFile, \r
- PCVOID pBuffer, \r
- DWORD cbWrite, \r
- PDWORD pcbWritten, \r
- OVERLAPPED *pOverlapped )\r
-{\r
- BOOL result;\r
-\r
- yfsd_LockYAFFS();\r
- RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));\r
-\r
- result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return result;\r
-}\r
-\r
-BOOL YFSD_WriteFileWithSeek( \r
- PFILE pFile, \r
- PCVOID pBuffer, \r
- DWORD cbWrite, \r
- PDWORD pcbWritten, \r
- OVERLAPPED *pOverlapped,\r
- DWORD dwLowOffset, \r
- DWORD dwHighOffset )\r
-{\r
- BOOL result;\r
- DWORD rememberedOffset;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));\r
-\r
- \r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- rememberedOffset = pFile->offset;\r
-\r
- pFile->offset = dwLowOffset;\r
- // ignore high offset for now\r
-\r
- result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);\r
-\r
- //pFile->offset = rememberedOffset;\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return result;\r
-}\r
-\r
-DWORD YFSD_SetFilePointer( \r
- PFILE pFile, \r
- LONG lDistanceToMove, \r
- PLONG pDistanceToMoveHigh, \r
- DWORD dwMoveMethod )\r
-{\r
- // ignore high offset for now\r
-\r
- DWORD offset = 0xFFFFFFFF;\r
- DWORD oldPos;\r
- int fileSize;\r
- int seekNegative = 0;\r
-\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return offset;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
-\r
- oldPos = pFile->offset;\r
-\r
- if(dwMoveMethod == FILE_BEGIN)\r
- {\r
- if(lDistanceToMove >= 0)\r
- { \r
- offset = pFile->offset = lDistanceToMove;\r
- }\r
- else\r
- {\r
- seekNegative = 1;\r
- }\r
- }\r
- else if(dwMoveMethod == FILE_END)\r
- {\r
- fileSize = yaffs_GetObjectFileLength(pFile->obj);\r
- if(fileSize >= 0 &&\r
- (fileSize + lDistanceToMove) >= 0)\r
- {\r
- offset = pFile->offset = fileSize + lDistanceToMove;\r
- }\r
- else\r
- {\r
- seekNegative = 1;\r
- }\r
- }\r
- else if(dwMoveMethod == FILE_CURRENT)\r
- {\r
- if(pFile->offset + lDistanceToMove >= 0)\r
- {\r
- offset = pFile->offset = pFile->offset + lDistanceToMove; \r
- }\r
- else\r
- {\r
- seekNegative = 1;\r
- }\r
- }\r
-\r
- if(seekNegative)\r
- {\r
- SetLastError(ERROR_NEGATIVE_SEEK);\r
- \r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",\r
- dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));\r
-\r
- return offset;\r
-\r
-}\r
-\r
-DWORD YFSD_GetFileSize( \r
- PFILE pFile, \r
- PDWORD pFileSizeHigh )\r
-{\r
- int fileSize;\r
- \r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));\r
- \r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return -1;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- fileSize = yaffs_GetObjectFileLength(pFile->obj);\r
-\r
- yfsd_UnlockYAFFS();\r
- if(pFileSizeHigh)\r
- *pFileSizeHigh = 0;\r
-\r
- return fileSize;\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_GetFileInformationByHandle( \r
- PFILE pFile,\r
- PBY_HANDLE_FILE_INFORMATION pFileInfo )\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));\r
-\r
- if(!pFile || !pFile->obj || !pFileInfo)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);\r
- yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);\r
- yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);\r
- yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);\r
- pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK? \r
- pFileInfo->nFileSizeHigh = 0;\r
- pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj); \r
- pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT\r
- pFileInfo->nFileIndexHigh = 0; \r
- pFileInfo->nFileIndexLow = pFile->obj->objectId;\r
- pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOL YFSD_FlushFileBuffers(PFILE pFile )\r
-{\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
- int nameExists = 0;\r
- yfsd_Volume *vol = NULL;\r
- DWORD attribs = 0;\r
- DWORD objSize = 0;\r
- DWORD mtime[2];\r
-\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- yaffs_FlushFile(pFile->obj,1);\r
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
- objSize = yaffs_GetObjectFileLength(pFile->obj);\r
- mtime[0] = pFile->obj->win_mtime[0];\r
- mtime[1] = pFile->obj->win_mtime[1];\r
- if(pFile->fullName)\r
- {\r
- wcscpy(fpn,pFile->fullName);\r
- nameExists = 1;\r
- }\r
- vol = pFile->myVolume;\r
-\r
- yfsd_UnlockYAFFS();\r
- \r
- if(vol && vol->shellFunction && nameExists)\r
- {\r
- FILECHANGEINFO fc;\r
- \r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_UPDATEITEM;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)fpn;\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- vol->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
- //yfsd_ShellDirectoryChanged(vol,fpn);\r
- }\r
-\r
- \r
- return TRUE;\r
-}\r
-\r
-BOOL YFSD_GetFileTime( \r
- PFILE pFile, \r
- FILETIME *pCreation, \r
- FILETIME *pLastAccess, \r
- FILETIME *pLastWrite )\r
-{\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
-\r
- if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);\r
- if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);\r
- if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOL YFSD_SetFileTime( \r
- PFILE pFile, \r
- CONST FILETIME *pCreation, \r
- CONST FILETIME *pLastAccess, \r
- CONST FILETIME *pLastWrite )\r
-{\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
- int nameExists = 0;\r
- int result = FALSE;\r
- yfsd_Volume *vol = NULL;\r
- DWORD attribs = 0;\r
- DWORD objSize = 0;\r
- DWORD mtime[2];\r
-\r
- \r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
- \r
- \r
- yfsd_LockYAFFS();\r
-\r
- if(pCreation) \r
- {\r
- yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);\r
- pFile->obj->dirty = 1;\r
- }\r
- if(pLastAccess)\r
- {\r
- yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);\r
- pFile->obj->dirty = 1;\r
- }\r
- if(pLastWrite)\r
- {\r
- yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);\r
- pFile->obj->dirty = 1;\r
- }\r
- if(pCreation || pLastAccess || pLastWrite)\r
- {\r
- result = yaffs_FlushFile(pFile->obj,0);\r
- }\r
-\r
- if(result)\r
- {\r
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
- objSize = yaffs_GetObjectFileLength(pFile->obj);\r
- mtime[0] = pFile->obj->win_mtime[0];\r
- mtime[1] = pFile->obj->win_mtime[1];\r
- if(pFile->fullName)\r
- {\r
- wcscpy(fpn,pFile->fullName);\r
- nameExists = 1;\r
- }\r
- vol = pFile->myVolume;\r
- }\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- // Call shell function\r
- if(nameExists && result && vol && vol->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- \r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_UPDATEITEM;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)fpn;\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- vol->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
- //yfsd_ShellDirectoryChanged(vol,fpn);\r
- }\r
-\r
- return TRUE;\r
-}\r
- \r
-BOOL YFSD_SetEndOfFile( \r
-PFILE pFile )\r
-{\r
-\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
- int nameExists = 0;\r
- yfsd_Volume *vol = NULL;\r
- DWORD attribs = 0;\r
- DWORD objSize = 0;\r
- DWORD mtime[2];\r
- static unsigned char zeros[512];\r
-\r
- int result;\r
- BOOL retVal = FALSE;\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));\r
-\r
- if(!pFile || !pFile->obj)\r
- {\r
- SetLastError(ERROR_INVALID_HANDLE);\r
- return FALSE;\r
- }\r
-\r
- yfsd_LockYAFFS();\r
- result = yaffs_ResizeFile(pFile->obj,pFile->offset);\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));\r
-\r
- // Resize only works if we're shortening the file.\r
- // If the result is shorter than the offset, then we need to write zeros....\r
- // \r
- if(result != pFile->offset)\r
- {\r
- if(result < pFile->offset)\r
- {\r
-\r
- int nBytes = pFile->offset - result;\r
- int thisWriteSize;\r
- int written;\r
- BOOL ok = TRUE;\r
-\r
- memset(zeros,0,512);\r
-\r
- pFile->offset = result;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));\r
- while(nBytes > 0 && ok)\r
- {\r
- thisWriteSize = (nBytes > 512) ? 512 : nBytes;\r
-\r
- ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written); \r
- if(written != thisWriteSize)\r
- {\r
- ok = FALSE;\r
- }\r
-\r
- nBytes -= thisWriteSize;\r
- }\r
-\r
- retVal = ok;\r
- }\r
- else\r
- {\r
-\r
- SetLastError(ERROR_ACCESS_DENIED);\r
- retVal = FALSE;\r
- }\r
- }\r
- else\r
- {\r
- retVal = TRUE;\r
- }\r
- if(retVal)\r
- {\r
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
- objSize = yaffs_GetObjectFileLength(pFile->obj);\r
- mtime[0] = pFile->obj->win_mtime[0];\r
- mtime[1] = pFile->obj->win_mtime[1];\r
- if(pFile->fullName)\r
- {\r
- wcscpy(fpn,pFile->fullName);\r
- nameExists = 1;\r
- }\r
- vol = pFile->myVolume;\r
- }\r
-\r
-\r
- yfsd_UnlockYAFFS();\r
-\r
- if(nameExists && retVal && vol && vol->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- \r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_UPDATEITEM;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)fpn;\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- vol->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
- //yfsd_ShellDirectoryChanged(vol,fpn);\r
- }\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));\r
-\r
-\r
- \r
- return retVal;\r
-}\r
-\r
-BOOL YFSD_DeviceIoControl( \r
- PFILE pFile, \r
- DWORD dwIoControlCode, \r
- PVOID pInBuf, \r
- DWORD nInBufSize, \r
- PVOID pOutBuf, \r
- DWORD nOutBufSize, \r
- PDWORD pBytesReturned, \r
- OVERLAPPED *pOverlapped )\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));\r
-\r
- return FALSE;\r
-}\r
-\r
-BOOL YFSD_CloseFile( PFILE pFile )\r
-{\r
- WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];\r
- int nameExists = 0;\r
- yfsd_Volume *vol = NULL;\r
- DWORD attribs = 0;\r
- DWORD objSize = 0;\r
- DWORD mtime[2];\r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));\r
-\r
- yfsd_LockYAFFS();\r
-\r
- if(!pFile)\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));\r
- }\r
- else\r
- {\r
- if(pFile->obj)\r
- {\r
- pFile->obj->inUse--;\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));\r
- yaffs_FlushFile(pFile->obj,1);\r
- attribs = yfsd_GetObjectWinAttributes(pFile->obj);\r
- objSize = yaffs_GetObjectFileLength(pFile->obj);\r
- mtime[0] = pFile->obj->win_mtime[0];\r
- mtime[1] = pFile->obj->win_mtime[1];\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));\r
- if(pFile->fullName)\r
- {\r
- wcscpy(fpn,pFile->fullName);\r
- nameExists = 1;\r
- }\r
- vol = pFile->myVolume;\r
- yfsd_PutWinFile(pFile);\r
- }\r
- else\r
- {\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));\r
- }\r
-\r
- }\r
- yfsd_UnlockYAFFS();\r
-\r
-\r
- if(nameExists && vol && vol->shellFunction)\r
- {\r
- FILECHANGEINFO fc;\r
- \r
- fc.cbSize = sizeof(FILECHANGEINFO);\r
- fc.wEventId = SHCNE_UPDATEITEM;\r
- fc.uFlags = SHCNF_PATH;\r
- fc.dwItem1 = (DWORD)fpn;\r
- fc.dwItem2 = 0;\r
- fc.dwAttributes = attribs;\r
- yfsd_U32sToWinFileTime(mtime,&fc.ftModified);\r
- fc.nFileSize = objSize;\r
-\r
- vol->shellFunction(&fc);\r
- RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));\r
- //yfsd_ShellDirectoryChanged(vol,fpn);\r
- }\r
-\r
- \r
-\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));\r
-\r
- return TRUE;\r
-\r
-}\r
-\r
-\r
-BOOL YFSD_CloseVolume(PVOLUME pVolume )\r
-{\r
- RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));\r
- yfsd_FlushAllFiles();\r
- return TRUE;\r
-}\r
-\r
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
+ * yaffsfsd.c: FSD interface funtions for WinCE.
+ *
+ * Copyright (C) 2002 Trimble Navigation Ltd.
+ *
+ * Created by Charles Manning <charles.manning@trimble.co.nz>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details. You should have received a
+ * copy of the GNU General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Acknowledgements:
+ * Various clean-ups and WinCE4 support by Steve Fogle and Lynn Winter
+ * $Id: yaffsfsd.c,v 1.4 2003-01-31 03:30:33 charles Exp $
+ */
+#include <windows.h>
+#include <extfile.h>
+#include <yaffs_guts.h>
+#include <ynandif.h>
+//slf021104b begin
+#include <diskio.h>
+//slf021104b end
+
+#define MAX_WIN_FILE 200
+#define YFSD_NAME_LENGTH 128
+#define YFSD_FULL_PATH_NAME_SIZE 500
+
+
+#define YFSD_DISK_NAME L"Disk"
+#define YFSD_BOOT_NAME L"Boot"
+
+#define PARTITION_START_NUMBER (1280)
+
+
+// if this is defined the there will be a constant message box raised to display status
+//#define MSGBOX_DISPLAY
+
+
+//#define MSGSTATE 1
+#define MSGSTATE 0
+//#define DISABLE_BOOT_PARTITION
+//slf021105a begin
+// Define DO_PARTITION_TABLE to cause the partition table
+// information to be retrieved from the block driver.
+// Can define this in your sources file.
+//#define DO_PARTITION_TABLE
+// How many partitions the disk might have. 2 gives
+// space for the "Disk" and "Boot" partitions.
+#define MAXPARTITIONS (2)
+//slf021105a end
+
+//unsigned yaffs_traceMask=0xffffffff;
+unsigned yaffs_traceMask=0;
+
+
+typedef struct
+{
+ yaffs_Device dev;
+ DWORD hdsk;
+ DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
+ BOOL isMounted;
+ BOOL configured;
+// DWORD guard0[100];
+// DWORD guard1[100];
+ SHELLFILECHANGEFUNC_t shellFunction;
+ PWSTR volName;
+} yfsd_Volume;
+
+typedef struct
+{
+ yaffs_Object *obj;
+ DWORD offset;
+ BOOL isopen;
+ BOOL dirty;
+ WCHAR *fullName;
+ yfsd_Volume *myVolume;
+ BOOL writePermitted;
+ BOOL readPermitted;
+ BOOL shareRead;
+ BOOL shareWrite;
+
+} yfsd_WinFile;
+
+struct yfsd_FoundObjectStruct
+{
+ yaffs_Object *obj;
+ struct yfsd_FoundObjectStruct *next;
+};
+
+typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
+
+typedef struct
+{
+ yaffs_Object *dir;
+ char pattern[YFSD_NAME_LENGTH+1];
+ yaffs_FoundObject *foundObjects;
+} yfsd_WinFind;
+
+
+
+#define PSEARCH yfsd_WinFind*
+
+#define PVOLUME yfsd_Volume*
+#define PFILE yfsd_WinFile*
+
+#define FSD_API YFSD
+
+#include <fsdmgr.h>
+
+//slf021105a begin
+//static yfsd_Volume disk_volume;
+//static yfsd_Volume boot_volume;
+static yfsd_Volume * disk_volumes[MAXPARTITIONS];
+//slf021105a end;
+
+static CRITICAL_SECTION yaffsLock;
+static CRITICAL_SECTION winFileLock;
+
+static int yaffsLockInited = 0;
+
+static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
+
+#if 0
+static yfsd_SetGuards(void)
+{
+ int i;
+ for(i = 0; i < 100; i++)
+ {
+ yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
+ }
+}
+
+static void yfsd_CheckGuards(void)
+{
+ int i;
+ int found;
+ for(i = found = 0; i < 100 && !found; i++)
+ {
+ if(yfsd_volume.guard0[i] != i)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+ found = 1;
+ }
+ if(yfsd_volume.guard1[i] != i)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
+ found = 1;
+ }
+ }
+}
+#endif
+
+
+#ifdef MSGBOX_DISPLAY
+DWORD WINAPI yfsd_MessageThread(LPVOID param)
+{
+ yaffs_Device *dev = (yaffs_Device *)param;
+ TCHAR dataBuffer[1000];
+ Sleep(10000);
+
+ // note : if the device gets free'd from under us, we will cause an exception in the loop
+ while (1)
+ {
+ wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"
+ L"nErasedBlocks %i\r\n"
+ L"allocationBlock %i\r\n"
+ L"allocationPage %i\r\n"
+ L"garbageCollectionRequired %i\r\n"
+ L"nRetiredBlocks %i\r\n"
+ L"cacheHits %i\r\n"
+ L"eccFixed %i\r\n"
+ L"eccUnfixed %i\r\n"
+ L"tagsEccFixed %i\r\n"
+ L"tagsEccUnfixed %i\r\n",
+ dev->nShortOpCaches,
+ dev->nErasedBlocks,
+ dev->allocationBlock,
+ dev->allocationPage,
+ dev->garbageCollectionRequired,
+ dev->nRetiredBlocks,
+ dev->cacheHits,
+ dev->eccFixed,
+ dev->eccUnfixed,
+ dev->tagsEccFixed,
+ dev->tagsEccUnfixed);
+
+ MessageBox(NULL,
+ dataBuffer,
+ L"YAFFS PROC INFO",
+ MB_OK);
+ Sleep(1);
+ }
+}
+#endif
+
+void yfsd_LockWinFiles(void)
+{
+ //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
+ EnterCriticalSection(&winFileLock);
+}
+void yfsd_UnlockWinFiles(void)
+{
+ //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
+ LeaveCriticalSection(&winFileLock);
+}
+
+int lockwaits;
+
+void yfsd_LockYAFFS(void)
+{
+ //yfsd_CheckGuards();
+ //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
+ lockwaits++;
+ EnterCriticalSection(&yaffsLock);
+ //RETAILMSG (MSGSTATE, (L" locked\r\n"));
+}
+void yfsd_UnlockYAFFS(void)
+{
+ //yfsd_CheckGuards();
+ //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
+ LeaveCriticalSection(&yaffsLock);
+ lockwaits--;
+ //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
+}
+
+
+void yfsd_InitialiseWinFiles(void)
+{
+ int i;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
+
+ InitializeCriticalSection(&winFileLock);
+
+ yfsd_LockWinFiles();
+ for(i = 0; i < MAX_WIN_FILE; i++)
+ {
+ yfsd_winFile[i].isopen = 0;
+ }
+ yfsd_UnlockWinFiles();
+}
+
+yfsd_WinFile * yfsd_GetWinFile(void)
+{
+ int i;
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
+
+ yfsd_LockWinFiles();
+
+ for(i = 0; i < MAX_WIN_FILE; i++)
+ {
+ if(!yfsd_winFile[i].isopen)
+ {
+ yfsd_winFile[i].isopen = 1;
+ yfsd_winFile[i].writePermitted = 0;
+ yfsd_winFile[i].readPermitted = 0;
+ yfsd_winFile[i].shareRead = 0;
+ yfsd_winFile[i].shareWrite = 0;
+ yfsd_winFile[i].dirty = 0;
+ yfsd_winFile[i].fullName = NULL;
+ yfsd_winFile[i].obj = NULL;
+
+ yfsd_UnlockWinFiles();
+ return &yfsd_winFile[i];
+ }
+ }
+
+ yfsd_UnlockWinFiles();
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
+
+ return NULL;
+}
+
+void yfsd_PutWinFile(yfsd_WinFile *f)
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
+ yfsd_LockWinFiles();
+ f->isopen = 0;
+ f->obj = NULL;
+ if(f->fullName)
+ {
+ free(f->fullName);
+ f->fullName = NULL;
+ }
+
+ yfsd_UnlockWinFiles();
+}
+
+
+
+void yfsd_FlushAllFiles(void)
+{
+ int i;
+ RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
+
+ yfsd_LockYAFFS();
+ yfsd_LockWinFiles();
+ for(i = 0; i < MAX_WIN_FILE; i++)
+ {
+ if(yfsd_winFile[i].isopen &&
+ yfsd_winFile[i].obj)
+ {
+ yaffs_FlushFile(yfsd_winFile[i].obj,1);
+ }
+ }
+ yfsd_UnlockWinFiles();
+ yfsd_UnlockYAFFS();
+}
+
+//slf021104d begin
+//////////////////////////////////////////////////////////////////////
+// Search through winFiles to see if any are open.
+
+BOOL yfsd_FilesOpen(void)
+{
+ int i;
+ BOOL rval;
+ RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
+
+ yfsd_LockWinFiles();
+ for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
+ {
+ if(yfsd_winFile[i].isopen)
+ {
+ rval = TRUE;
+ break;
+ }
+ }
+ yfsd_UnlockWinFiles();
+ return rval;
+}
+//slf021104d end
+
+PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
+{
+
+ // todo check for bounds
+ //slf021104b begin
+ //volName already has the initial backslash if it needs it.
+ //wcscpy(fpn,L"\\");
+ //wcscat(fpn,vol->volName);
+ wcscpy(fpn,vol->volName);
+ //slf021104b end
+ if(pathName[0] != '\\')
+ {
+ wcscat(fpn,L"\\");
+ }
+ wcscat(fpn,pathName);
+
+ return fpn;
+
+}
+
+
+// FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
+
+void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
+{
+
+ wft->dwLowDateTime = target[0];
+ wft->dwHighDateTime = target[1];
+
+}
+
+void yfsd_NullWinFileTime(FILETIME *wft)
+{
+ wft->dwLowDateTime = 0;
+ wft->dwHighDateTime = 0;
+}
+
+void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
+{
+ target[0] = wft->dwLowDateTime;
+ target[1] = wft->dwHighDateTime;
+}
+
+void yfsd_WinFileTimeNow(__u32 target[2])
+{
+ SYSTEMTIME st;
+ FILETIME ft;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st,&ft);
+ yfsd_WinFileTimeToU32s(&ft,target);
+}
+
+// Cut down the name to the parent directory, then inform the shell of
+// a change to the directory.
+void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
+{
+ WCHAR str[500];
+ int i;
+ wcscpy(str,fullPathName);
+
+ i = wcslen(str) - 1;
+
+ if(i > 0)
+ {
+ str[i] = 0;
+ i--;
+ }
+
+ // Curveball if the name is a directory (ie. we're doing an update of
+ // a directory because we added a directory item). , then it might end in a \
+ // which we must toss first
+ if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
+ {
+ str[i] = 0;
+ i--;
+ }
+
+ // Ok, now strip back...
+
+ while(i >= 0 && str[i] != '\\' && str[i] != '/')
+ {
+ str[i] = 0;
+ i--;
+ }
+
+ if(pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEDIR;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)str;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = 0;
+ yfsd_NullWinFileTime(&fc.ftModified);
+ fc.nFileSize = 0;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
+
+ }
+
+
+}
+
+
+// Minimal name test for now
+BOOL yfsd_NameIsValid (const char *name)
+{
+ int length = strlen(name);
+
+ return (length > 0 && length <= YFSD_NAME_LENGTH);
+
+}
+
+// File attributes:
+// Wince understands the following attributes of any use to YAFFS:
+//
+// ARCHIVE
+// HIDDEN
+// READONLY
+// SYSTEM
+// TEMPORARY
+//
+// Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
+//
+// It also understands NORMAL. If no other flag is set, then set NORMAL.
+// If any of the above are set, then NORMAL must **not** be set.
+// Ignore this and the WinCE Explorer barfs the file.
+//
+//
+// in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
+
+// The following are valid ones we get presented with,
+// but must filter out the stuff we don't unserstand
+//#define FILE_ATTRIBUTE_READONLY 0x00000001
+//#define FILE_ATTRIBUTE_HIDDEN 0x00000002
+//#define FILE_ATTRIBUTE_SYSTEM 0x00000004
+//#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+//#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+//#define FILE_ATTRIBUTE_INROM 0x00000040
+//#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
+//#define FILE_ATTRIBUTE_NORMAL 0x00000080
+//#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+//#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+//#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+//#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+//#define FILE_ATTRIBUTE_OFFLINE 0x00001000
+//#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
+//#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+//#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
+
+
+BOOL yfsd_CheckValidAttributes(DWORD attribs)
+{
+
+ RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
+
+#if 0
+ // If NORMAL, then nothing else
+ if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
+ return FALSE;
+ if(attribs == FILE_ATTRIBUTE_NORMAL)
+ return TRUE;
+#endif
+ // Check that the bits are in the valid set
+ if(attribs & ~(0x3FE7))
+ return FALSE;
+
+ return TRUE;
+
+}
+DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
+{
+
+ DWORD result;
+
+ result = obj->st_mode &
+ (FILE_ATTRIBUTE_READONLY |
+ FILE_ATTRIBUTE_ARCHIVE |
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_SYSTEM);
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
+
+ if(result & ~FILE_ATTRIBUTE_NORMAL)
+ {
+ result &= ~FILE_ATTRIBUTE_NORMAL;
+ }
+ else
+ {
+ result = FILE_ATTRIBUTE_NORMAL;
+ }
+
+
+ return result;
+}
+
+
+
+/*
+* Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
+* reached. Characters are copied from input into output until the above stop
+* condition is reached - output is then given a '\0'. output must be at least
+* as large as outSize
+*/
+static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
+{
+ int counter = 0;
+ char *t = output;
+ /* strip any starting \'s */
+ //RETAILMSG(1, (L"\r\nParsing.. "));
+ while (*input == '\\' || *input == '/') input++, counter++;
+
+ for (; counter < outSize - 1; counter++)
+ {
+ if (*input == '\0' ||
+ ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'
+ {
+ counter = -1; // break & tell people we've run to the end
+ break;
+ }
+ if (*input == '\\' || *input == '/')
+ break;
+ //RETAILMSG(1, (L"%c", *input));
+ *output = (char) (*input);
+ input++;
+ output++;
+ }
+ *output++ = '\0';
+ *output = '\0';
+// RETAILMSG(1, (L"\r\nOut %a\r\n", t));
+
+ return counter;
+}
+
+/*
+* Since the notion of paths as WinCE sees them and as YAFFS sees them
+* is different, we needed a helper function to search from the root of
+* device along the string in path. The processed pointer is set to where
+* abouts in the string the function was able to search up to.
+*/
+yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
+{
+ // a buffer to keep the current chunk of path we're talking about it
+ char pathChunk[255];
+ int chunkSize;
+ int counter;
+ // the current object we are at
+ yaffs_Object *current;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
+ // start at the root of this device
+ current = yaffs_Root(device);
+ *processed = '\0';
+
+ do
+ {
+ // parse chunks until we run out
+ chunkSize = parseToNextSlash(path, pathChunk, 255);
+// RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
+ if (chunkSize == -1)
+ break;
+ // move the path pointer along
+ path += chunkSize;
+ // try and find the next yaffs object by chunkname
+ current = yaffs_FindObjectByName(current, pathChunk);
+ if (current == 0)
+ {
+ processed[0] = '\0';
+ return 0;
+ }
+ } while (1);
+
+ for (counter = 0; counter < length; counter++)
+ {
+ // Get the rest of the string
+ processed[counter] = pathChunk[counter];
+ if (pathChunk[counter] == '\0')
+ break;
+ }
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
+
+ return current;
+}
+
+
+yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
+{
+ yaffs_Object *obj = NULL;
+ yaffs_Object *parent = NULL;
+ char name[YFSD_NAME_LENGTH+1];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
+
+ parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+ if(parent && yfsd_NameIsValid(name))
+ {
+ obj = yaffs_FindObjectByName(parent,name);
+ }
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
+
+ return obj;
+}
+
+BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
+{
+ //slf021104b Begin
+ WCHAR szName[MAX_PATH];
+ DWORD dwAvail;
+ //slf021104b end
+ RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
+ //slf021104b Begin filled in later.
+ //vol->volName = volName;
+ //slf021104b end
+
+
+ yfsd_LockYAFFS();
+
+ //slf021220a Begin Cleanup block driver interface
+#if _WINCEOSVER >= 400
+ // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.
+ vol->dev.genericDevice = (PVOID)hdsk;
+#endif
+ //slf021220a End Cleanup block driver interface
+
+ //Mount/initialise YAFFs here
+ //slf021127a begin check for error returns!
+ if (ynandif_InitialiseNAND(&vol->dev))
+ {
+ //slf021127a end check for error returns!
+ vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
+ vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
+ vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
+ vol->dev.initialiseNAND = ynandif_InitialiseNAND;
+ vol->dev.startBlock = startBlock;
+ if (endBlock != -1)
+ vol->dev.endBlock = endBlock;
+ vol->dev.nShortOpCaches = 10; // a nice number of caches.
+ vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+ vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+ vol->dev.nReservedBlocks = 5; // a nice reserve size
+
+
+ // nBlocks is set the total size of the disk, not the partition
+ // vol->dev.nBlocks = endBlock - startBlock + 1;
+
+ // qnand_EraseAllBlocks(&vol->dev);
+
+ //slf021127a begin check for error returns!
+ if (yaffs_GutsInitialise(&vol->dev))
+ {
+ //slf021127a end check for error returns!
+ RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
+
+ RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
+ vol->dev.startBlock,vol->dev.endBlock,
+ vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
+
+
+#if 0
+ for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
+ {
+ switch(vol->dev.blockInfo[i].blockState)
+ {
+ case YAFFS_BLOCK_STATE_DEAD:
+
+ RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
+ deadBlox++;
+ break;
+ case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
+ case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
+ case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
+ case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
+ default:
+ RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
+ break;
+ }
+ }
+
+ RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",
+ deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
+
+#endif
+
+//slf021127a begin check for error returns!
+ vol->isMounted = 1;
+ }
+ }
+//slf021127a begin check for error returns!
+
+ yfsd_UnlockYAFFS();
+
+//slf021127a begin check for error returns!
+// vol->isMounted = 1;
+//slf021127a begin check for error returns!
+
+ //slf021104b begin
+ //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
+ // If the caller passed a volume name use it.
+ if (volName[0])
+ wcscpy( szName, volName);
+#if WINCEOSVER >= 400
+ // The user passed an empty volume name. On CE 4.xx try to get
+ // if from the block driver (which got it from the registry).
+ else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL))
+#else
+ else
+#endif
+ {
+ // Didn't get a volume name so use "Disk" by default.
+ wcscpy( szName, YFSD_DISK_NAME);
+ }
+ vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
+ //slf021104b end
+
+ if(vol->mgrVolume)
+ {
+ //slf021104b Begin
+ // Get some space for the volume name.
+ vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
+ if (vol->volName)
+ {
+#if WINCEOSVER >= 400
+ // Get the name we were really mounted under.
+ FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
+
+ // If we got mounted as root then throw away the backslash
+ // so we won't get a double backslash when volName is
+ // prepended to the path in the full path name calculation
+ // that is used for shell callbacks.
+ if (0 == wcscmp(vol->volName,L"\\"))
+ vol->volName[0] = 0;
+#else
+ // Use the name we asked to be mounted under for
+ // our root.
+ wcscpy(vol->volName,L"\\");
+ wcscat(vol->volName, szName);
+#endif
+ }
+ //slf021104b end
+ return TRUE;
+ }
+ else
+ {
+ vol->isMounted = 0;
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+}
+
+
+BOOL YFSD_MountDisk(HDSK hdsk)
+{
+//slf021105a begin
+#ifdef DO_PARTITION_TABLE
+ ynandif_partition PartTable[MAXPARTITIONS];
+ DWORD dwAvail;
+ int i;
+ BOOL rval = FALSE;
+#endif
+//slf021105a end
+ int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
+ //int i;
+ // Called to mount a disk.
+ // NB THis call might happen redundantly.
+ //
+ //
+ // If yaffs is not initialised, then call the
+ // initialisation function
+ //
+ RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
+
+ if (!yaffsLockInited)
+ {
+ InitializeCriticalSection(&yaffsLock);
+ yfsd_InitialiseWinFiles();
+ yaffsLockInited = 1;
+ }
+
+ //slf021105a begin
+ memset(disk_volumes,0,sizeof(disk_volumes));
+#ifdef DO_PARTITION_TABLE
+ memset(&PartTable,0,sizeof(PartTable));
+ // Call the block driver to get the partition table from it.
+ if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL))
+ {
+ // Scan throught the table it return.
+ for (i=0; i<MAXPARTITIONS; i++)
+ {
+ // At the very lease check that the end is later than the beginning
+ // and don't let it start at 0.
+ // Probably could do more thorough checking but I trust the block
+ // driver.
+ if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))
+ {
+ // Found a partion. Get a volume structure to hold it.
+ disk_volumes[i] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[i])
+ {
+ memset(disk_volumes[i],0,sizeof(yfsd_Volume));
+ // Go init the volume. Note that if the block driver wants the
+ // name to come from the registry it will have returned an
+ // empty name string.
+ YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
+ if (disk_volumes[i]->isMounted)
+ rval = TRUE; //Hey, we found at least on partition.
+ }
+ }
+ }
+ }
+
+ return rval;
+
+#else
+#ifdef DISABLE_BOOT_PARTITION
+ // Only want disk volume
+ disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[0])
+ {
+ memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+ YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
+
+ if(disk_volumes[0].isMounted)
+ {
+ return TRUE;
+ }
+ }
+ if (disk_volumes[0])
+ {
+ free(disk_volumes[0];
+ disk_volumes[0] = NULL;
+ }
+#else
+ // Want both boot and disk
+ disk_volumes[0] = malloc(sizeof(yfsd_Volume));
+ disk_volumes[1] = malloc(sizeof(yfsd_Volume));
+ if (disk_volumes[0] && disk_volumes[1])
+ {
+ memset(disk_volumes[0],0,sizeof(yfsd_Volume));
+ memset(disk_volumes[1],0,sizeof(yfsd_Volume));
+ YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+ YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+
+#ifdef MSGBOX_DISPLAY
+ // pass the device we are sniffing to the thread
+ CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);
+#endif
+
+ if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
+ {
+ return TRUE;
+ }
+ }
+
+ // If we got this far something went wrong. Make sure to
+ // free any memory we allocated.
+ if (disk_volumes[0])
+ {
+ if (disk_volumes[0]->volName)
+ {
+ free(disk_volumes[0]->volName);
+ }
+ free(disk_volumes[0]);
+ disk_volumes[0] = NULL;
+ }
+ if (disk_volumes[1])
+ {
+ if (disk_volumes[1]->volName)
+ {
+ free(disk_volumes[1]->volName);
+ }
+ free(disk_volumes[1]);
+ disk_volumes[1] = NULL;
+ }
+#endif
+
+ return FALSE;
+
+ // Only want disk volume
+// YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
+//
+//
+// if(disk_volume.isMounted)
+// {
+// return TRUE;
+// }
+//#else
+// // Want both boot and disk
+// YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
+// YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
+//
+//
+// if(disk_volume.isMounted && boot_volume.isMounted)
+// {
+// return TRUE;
+// }
+//#endif
+//
+// return FALSE;
+#endif
+//slf021105a end
+
+// yfsd_SetGuards();
+
+ // todo - get name from registry
+
+}
+
+
+BOOL YFSD_UnmountDisk(HDSK hdsk)
+{
+//slf021105a begin
+ int i;
+//slf021105a end
+ RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
+
+ //slf021104d begin
+ // If there are any files open don't let them dismount
+ // it or the system will get very confused.
+ if (yfsd_FilesOpen())
+ return FALSE;
+
+ //yfsd_FlushAllFiles();
+ //slf021104d end
+
+ yfsd_LockYAFFS();
+//slf021105a begin
+// yaffs_Deinitialise(&disk_volume.dev);
+// yaffs_Deinitialise(&boot_volume.dev);
+// yfsd_UnlockYAFFS();
+//
+// FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
+// FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
+
+ // Walk through the partions deinitializing, deregistering
+ // and freeing them.
+ for (i=0; i<MAXPARTITIONS; i++)
+ {
+ if (disk_volumes[i])
+ {
+ yaffs_Deinitialise(&(disk_volumes[i]->dev));
+//slf021220a Begin Cleanup block driver interface
+ ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));
+//slf021220a end Cleanup block driver interface
+ FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
+ if (disk_volumes[i]->volName)
+ {
+ free(disk_volumes[i]->volName);
+ }
+ free(disk_volumes[i]);
+ disk_volumes[i] = NULL;
+ }
+ }
+ yfsd_UnlockYAFFS();
+//slf021105a end
+ return TRUE;
+}
+
+
+BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
+{
+ // security attributes are ignored (should be NULL)
+
+ yaffs_Object *newDir = NULL;
+ yaffs_Object *parent = NULL;
+ char name[YFSD_NAME_LENGTH+1];
+ ULONG objSize;
+ DWORD attribs;
+ unsigned modifiedTime[2];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
+
+ yfsd_LockYAFFS();
+
+ parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+ //slf021101b begin
+ if (parent)
+ {
+ if(yfsd_NameIsValid(name))
+ {
+ newDir = yaffs_MknodDirectory(parent,name,0,0,0);
+ if(newDir)
+ {
+ objSize = yaffs_GetObjectFileLength(newDir);
+ attribs = yfsd_GetObjectWinAttributes(newDir);
+ modifiedTime[0] = newDir->win_mtime[0];
+ modifiedTime[1] = newDir->win_mtime[1];
+ }
+ else
+ {
+ if(yaffs_FindObjectByName(parent,name))
+ SetLastError(ERROR_ALREADY_EXISTS);
+ else
+ SetLastError(ERROR_DISK_FULL);
+ }
+ }
+ else
+ SetLastError(ERROR_INVALID_NAME);
+ }
+ else
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ }
+ //slf021101b end
+
+ yfsd_UnlockYAFFS();
+
+ // Call shell function to tell of new directory
+ if(newDir && pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_MKDIR;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ //yfsd_ShellDirectoryChanged(pVolume,fpn);
+
+ }
+
+//slf021101b begin
+// if(parent && !newDir)
+// {
+// SetLastError(ERROR_DISK_FULL);
+// }
+//slf021101b end
+
+ return newDir ? TRUE : FALSE;
+}
+
+
+BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
+{
+ int result = FALSE;
+ yaffs_Object *parent = NULL;
+ yaffs_Object *obj;
+ char name[YFSD_NAME_LENGTH+1];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));
+
+ yfsd_LockYAFFS();
+
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
+ if(!obj)
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ result = FALSE;
+ }
+ else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else if(obj->inUse)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else
+ {
+
+ parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
+
+ if(parent && yfsd_NameIsValid(name))
+ {
+ result = yaffs_Unlink(parent,name);
+ if(!result)
+ SetLastError(ERROR_DIR_NOT_EMPTY);
+ }
+ }
+
+ yfsd_UnlockYAFFS();
+
+ if(result && pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_RMDIR;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
+ fc.dwItem2 = 0;
+ fc.dwAttributes = 0;
+ yfsd_NullWinFileTime(&fc.ftModified);
+ fc.nFileSize = 0;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ yfsd_ShellDirectoryChanged(pVolume,fpn);
+ }
+
+ return result ? TRUE : FALSE;
+}
+
+
+DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
+{
+ yaffs_Object *obj = NULL;
+
+ DWORD result = 0xFFFFFFFF;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
+
+ yfsd_LockYAFFS();
+
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+ if(obj)
+ {
+ result = yfsd_GetObjectWinAttributes(obj);
+ }
+ else
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ }
+
+ yfsd_UnlockYAFFS();
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
+ return result;
+
+
+}
+
+BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
+{
+ yaffs_Object *obj = NULL;
+ DWORD mtime[2];
+ DWORD attribs;
+ DWORD objSize;
+
+ int result = 0;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
+
+ if(!yfsd_CheckValidAttributes(dwFileAttributes))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+
+ if(obj)
+ {
+ obj->st_mode = dwFileAttributes;
+ obj->dirty = 1;
+ result = yaffs_FlushFile(obj,0);
+ attribs = yfsd_GetObjectWinAttributes(obj);
+ objSize = yaffs_GetObjectFileLength(obj);
+ mtime[0] = obj->win_mtime[0];
+ mtime[1] = obj->win_mtime[1];
+ }
+ else
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ }
+
+ yfsd_UnlockYAFFS();
+
+ if(result && pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_ATTRIBUTES;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ //yfsd_ShellDirectoryChanged(pVolume,fpn);
+ }
+
+
+ return result;
+
+}
+
+BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
+{
+ int result = FALSE;
+ yaffs_Object *parent = NULL;
+ yaffs_Object *obj;
+ char name[YFSD_NAME_LENGTH+1];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
+
+ yfsd_LockYAFFS();
+
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ if(!obj)
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ result = FALSE;
+ }
+ else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else if(obj->inUse)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ result = FALSE;
+ }
+ else
+ {
+
+ parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+ if(parent && yfsd_NameIsValid(name))
+ {
+ result = yaffs_Unlink(parent,name);
+ if(!result)
+ SetLastError(ERROR_ACCESS_DENIED);
+ }
+ }
+
+ yfsd_UnlockYAFFS();
+
+ if(result && pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_DELETE;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+ fc.dwItem2 = 0;
+ fc.dwAttributes = -1;
+ yfsd_NullWinFileTime(&fc.ftModified);
+ fc.nFileSize = 0;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ yfsd_ShellDirectoryChanged(pVolume,fpn);
+ }
+
+ return result ? TRUE : FALSE;
+}
+
+BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+ yaffs_Object *newParent = NULL;
+ yaffs_Object *oldParent = NULL;
+ yaffs_Object *obj = NULL;
+ char oldName[YFSD_NAME_LENGTH+1];
+ char newName[YFSD_NAME_LENGTH+1];
+ int result = 0;
+ int objIsDir = 0;
+ DWORD attribs;
+ DWORD objSize;
+ DWORD mtime[2];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
+
+ yfsd_LockYAFFS();
+
+ oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
+ newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
+
+ if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
+ {
+ result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
+ if(!result)
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ }
+
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
+ if(obj)
+ {
+ objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
+ attribs = yfsd_GetObjectWinAttributes(obj);
+ objSize = yaffs_GetObjectFileLength(obj);
+ mtime[0] = obj->win_mtime[0];
+ mtime[1] = obj->win_mtime[1];
+ }
+ }
+ else
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ }
+
+ yfsd_UnlockYAFFS();
+
+
+ if(result && pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
+ WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
+ fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ yfsd_ShellDirectoryChanged(pVolume,fpn1);
+ yfsd_ShellDirectoryChanged(pVolume,fpn2);
+ }
+
+
+ return result ? TRUE : FALSE;
+
+}
+
+BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
+{
+ //slf021104c begin
+ BOOL fSuccess;
+ //slf021104c end
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
+
+ //slf021104c begin
+ if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
+ fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
+ return fSuccess;
+ //return FALSE;
+ //slf021104c end
+}
+
+BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
+{
+
+ int nChunks;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
+
+ yfsd_LockYAFFS();
+ nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
+ yfsd_UnlockYAFFS();
+
+ if(nChunks >= 0)
+ {
+ // Let's pretentd our clusters are the same size as eraseable blocks...
+ *pBytesPerSector = 512;
+ *pSectorsPerCluster =32;
+ *pFreeClusters = nChunks/32;
+ *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
+ }
+
+ return (nChunks >= 0)? TRUE : FALSE;
+
+
+
+}
+
+void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
+{
+ // Flags can be one of:
+ // FSNOTIFY_POWER_ON: no action required
+ // FSNOTIFY_POWER_OFF: flush all files
+ // FSNOTIFY_DEVICE_ON: no action required
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
+ if(dwFlags == FSNOTIFY_POWER_OFF)
+ {
+ yfsd_FlushAllFiles();
+ }
+
+}
+
+
+BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
+
+ pVolume->shellFunction = pfn;
+
+ return TRUE;
+}
+
+
+
+
+
+int iMatch(const char a, const char b)
+{
+ if (a == '?' || b == '?')
+ return 1;
+ return (toupper(a) == toupper(b));
+}
+
+void pString(const char *inp)
+{
+ while (*inp) RETAILMSG(1, (L"%c", *inp++));
+}
+
+int regularMatch(const char *regexp, const char *str)
+{
+// pString(regexp);
+// RETAILMSG(1, (L" "));
+// pString(str);
+// RETAILMSG(1, (L"\r\n"));
+
+ if (*regexp == 0 && *str == 0)
+ {
+ //RETAILMSG(1, (L"Match!\r\n"));
+ return 1;
+ }
+ if (*regexp == '*')
+ {
+ regexp++;
+ if (*regexp == 0) // end of the expression is a *, we must match
+ {
+ //RETAILMSG(1, (L"Match!\r\n"));
+ return 1;
+ }
+ while (!iMatch(*regexp, *str)) // throw away chars from str until we match
+ {
+ if (*str == 0) // if we're not at the end
+ {
+ // if we have .* left to match, but the str is finished then match it OK
+ if (regexp[0] == '.' && regexp[1] == '*')
+ {
+ //RETAILMSG(1, (L"Match!\r\n"));
+ return 1;
+ }
+ else
+ {
+ // the extension failed the match
+ //RETAILMSG(1, (L"No Match!\r\n"));
+ return 0;
+ }
+ }
+ str++;
+ }
+ // right now we should either eat more characters, or try to match
+ return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
+ }
+// compare chars until we hit another *, or we fail
+ while (iMatch(*regexp, *str))
+ {
+ if (*regexp == 0 && *str == 0)
+ {
+ //RETAILMSG(1, (L"Match!\r\n"));
+ return 1;
+ }
+ regexp++;
+ str++;
+ }
+
+ if (*regexp == 0 && *str == 0)
+ {
+ //RETAILMSG(1, (L"Match!\r\n"));
+ return 1;
+ }
+
+ if (*regexp == '*')
+ return regularMatch(regexp, str);
+
+ //RETAILMSG(1, (L"No Match!\r\n"));
+ return 0;
+}
+
+
+void yfsd_DeleteFinder(PSEARCH pSearch)
+{
+ if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
+ {
+ yaffs_FoundObject *it;
+ yaffs_FoundObject *temp;
+
+ it = pSearch->foundObjects;
+
+ while(it != NULL)
+ {
+ temp = it;
+ it = it->next;
+
+ free(temp);
+ }
+
+ pSearch->foundObjects = NULL;
+ }
+
+ pSearch->dir->inUse--;
+ free(pSearch);
+}
+
+BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
+{
+ //Iterate through the current list of objs already found and return true if already exists.
+ //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
+ BOOL found = FALSE;
+
+ yaffs_FoundObject *it;
+ it = pSearch->foundObjects;
+
+
+ while(it->next != NULL) //iterate through singly linked list.
+ {
+ if(it->obj == l)
+ {
+ found = TRUE;
+ break;
+ }
+ it = it->next;
+ }
+
+ if(!found)
+ {
+ //Add the item to the list.
+ //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
+ it->next = malloc(sizeof(yaffs_FoundObject));
+ it->next->next = NULL;
+ it->next->obj = 0;
+
+ it->obj = l;
+ }
+
+ return found;
+}
+
+#if 0
+// slower one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+ struct list_head *i;
+ int pos;
+ yaffs_Object *l;
+ BOOL found = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH+1];
+
+ if(!pSearch->foundObjects)
+ {
+ pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
+ pSearch->foundObjects->next = NULL;
+ pSearch->foundObjects->obj = 0;
+ }
+
+
+ yfsd_LockYAFFS();
+
+ pos = 0;
+ list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+ {
+
+ l = list_entry(i, yaffs_Object,siblings);
+
+ yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+ if(regularMatch(pSearch->pattern,name))
+ {
+ if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
+ {
+
+
+ found = 1;
+ //pSearch->currentPos++;
+
+ // fill out find data
+
+ pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
+
+ yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
+ yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
+ yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
+
+ pfd->nFileSizeHigh = 0;
+ pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
+ pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
+
+ MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
+
+ RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
+ pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
+ l->variant.fileVariant.scannedFileSize));
+ goto out_of_here;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+ }
+
+out_of_here:
+ yfsd_UnlockYAFFS();
+
+
+ if(!found)
+ {
+ SetLastError(ERROR_NO_MORE_FILES);
+ }
+ return found;
+
+}
+
+#else
+// faster one
+BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
+{
+
+ struct list_head *i;
+ yaffs_Object *l;
+ BOOL found = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH+1];
+
+ if(!pSearch->foundObjects)
+ {
+ pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
+ pSearch->foundObjects->next = NULL;
+ pSearch->foundObjects->obj = 0;
+ }
+
+
+ yfsd_LockYAFFS();
+
+ list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
+ {
+
+ l = list_entry(i, yaffs_Object,siblings);
+ if(!yfsd_ObjectAlreadyFound(pSearch,l))
+ {
+ // Only look at things we have not looked at already
+ yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+ if(regularMatch(pSearch->pattern,name))
+ {
+ found = 1;
+ // fill out find data
+
+ pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
+
+ yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
+ yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
+ yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
+
+ pfd->nFileSizeHigh = 0;
+ pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
+ pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
+
+ MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
+
+ RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
+ pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
+ l->variant.fileVariant.scannedFileSize));
+ goto out_of_here;
+ }
+
+ }
+
+
+ }
+
+out_of_here:
+ yfsd_UnlockYAFFS();
+
+
+ if(!found)
+ {
+ SetLastError(ERROR_NO_MORE_FILES);
+ }
+ return found;
+
+}
+#endif
+
+HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
+{
+
+ // Create a search context, register it, and do the first search
+
+ PSEARCH pSearch;
+ HANDLE h = INVALID_HANDLE_VALUE;
+ BOOL found = 0;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
+
+ pSearch = malloc(sizeof(yfsd_WinFind));
+ if(!pSearch)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ }
+
+ yfsd_LockYAFFS();
+
+ if(pSearch)
+ {
+ pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
+ pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
+ if(pSearch->dir)
+ {
+ pSearch->dir->inUse++;
+ }
+ else
+ {
+ free(pSearch);
+ pSearch = NULL;
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ }
+ }
+
+ yfsd_UnlockYAFFS();
+
+
+
+ if(pSearch)
+ {
+ found = yfsd_DoFindFile(pSearch,pfd);
+
+ if(found)
+ {
+ h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
+ if(h == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
+ }
+ }
+ else
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ }
+
+ if(h == INVALID_HANDLE_VALUE)
+ {
+ yfsd_DeleteFinder(pSearch);
+ }
+
+ }
+
+
+ return h;
+}
+
+BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
+ if(!pSearch)
+ {
+ return FALSE;
+ }
+ return yfsd_DoFindFile(pSearch,pfd);
+}
+
+BOOL YFSD_FindClose( PSEARCH pSearch )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
+ if(!pSearch)
+ {
+ return FALSE;
+ }
+ yfsd_DeleteFinder(pSearch);
+ return TRUE;
+}
+
+
+HANDLE YFSD_CreateFileW(
+ PVOLUME pVolume,
+ HANDLE hProc,
+ PCWSTR pwsFileName,
+ DWORD dwAccess,
+ DWORD dwShareMode,
+ PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
+ DWORD dwCreate,
+ DWORD dwFlagsAndAttributes,
+ HANDLE hTemplateFile ) // ignore
+{
+
+
+ yaffs_Object *parent = NULL;
+ yaffs_Object *obj = NULL;
+ char name[YFSD_NAME_LENGTH+1];
+ int mode;
+ yfsd_WinFile *f = NULL;
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ unsigned modifiedTime[2];
+ unsigned objSize;
+
+ BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
+ BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
+ BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
+ BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
+
+ BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
+
+ BOOL fileCreated = FALSE;
+
+ BOOL fAlwaysCreateOnExistingFile = FALSE;
+ BOOL fTruncateExistingFile = FALSE;
+
+
+ mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
+ if(writePermitted)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
+ }
+
+ if(!yfsd_CheckValidAttributes(mode))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+
+ parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
+
+
+ if(parent && yfsd_NameIsValid(name))
+ {
+
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // Get the object for this file if it exists (only once).
+ obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //slf021220b end Fix still more bugs in CreateFile.
+ if(dwCreate == CREATE_NEW)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
+
+ //slf021101c begin
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //slf021220b end Fix still more bugs in CreateFile.
+ if(!obj)
+ {
+ obj = yaffs_MknodFile(parent,name,mode,0,0);
+ if(!obj)
+ SetLastError(ERROR_DISK_FULL);
+ fileCreated = TRUE;
+ }
+ //slf021220b begin Fix still more bugs in CreateFile.
+ else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ obj = NULL;
+ SetLastError(ERROR_ALREADY_EXISTS);
+ }
+ //slf021220b end Fix still more bugs in CreateFile.
+ else
+ {
+ obj = NULL;
+ //slf021220b begin Fix still more bugs in CreateFile.
+ //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);
+ SetLastError(ERROR_FILE_EXISTS);
+ //slf021220b begin Fix still more bugs in CreateFile.
+ }
+ //slf021101c end
+ }
+ else if( dwCreate == OPEN_ALWAYS)
+ {
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //slf021220b end Fix still more bugs in CreateFile.
+ if(!obj)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
+ obj = yaffs_MknodFile(parent,name,mode,0,0);
+ if(!obj)
+ SetLastError(ERROR_DISK_FULL);
+ fileCreated = TRUE;
+
+ }
+ //slf021220b begin Fix still more bugs in CreateFile.
+ else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ obj = NULL;
+ SetLastError(ERROR_ACCESS_DENIED);
+ }
+ //slf021220b end Fix still more bugs in CreateFile.
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
+ }
+ }
+ else if(dwCreate == OPEN_EXISTING)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //slf021220b end Fix still more bugs in CreateFile.
+ if(!obj)
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ //slf021220b begin Fix still more bugs in CreateFile.
+ //slf021101c begin
+ // else
+ // if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
+ // {
+ // SetLastError(ERROR_ACCESS_DENIED);
+ // obj = NULL;
+ // }
+ //slf021101c end
+ else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ obj = NULL;
+ }
+ //slf021220b end Fix still more bugs in CreateFile.
+ }
+ else if(dwCreate == TRUNCATE_EXISTING)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //if(obj)
+ if (!writePermitted || (obj && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))
+ {
+ obj = NULL;
+ SetLastError(ERROR_ACCESS_DENIED);
+ }
+ else if(obj)
+ //slf021220b end Fix still more bugs in CreateFile.
+ {
+ // Indicate that file is to be truncated. This will happen later on assuming
+ // that a sharing violation does not occur and that we can get a file handle.
+ fTruncateExistingFile = TRUE;
+ }
+ else
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ }
+ }
+ else if(dwCreate == CREATE_ALWAYS)
+ {
+ //slf021220b begin Fix still more bugs in CreateFile.
+ // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
+ //slf021220b end Fix still more bugs in CreateFile.
+
+ if(!obj)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
+ obj = yaffs_MknodFile(parent,name,mode,0,0);
+ if(!obj)
+ SetLastError(ERROR_DISK_FULL);
+ fileCreated = TRUE;
+ }
+ //slf021220b begin Fix still more bugs in CreateFile.
+ else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ obj = NULL;
+ SetLastError(ERROR_ACCESS_DENIED);
+ }
+ //slf021220b end Fix still more bugs in CreateFile.
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
+ // Indicate that file is to be recreated. This will happen later on assuming
+ // that a sharing violation does not occur and that we can get a file handle.
+ fAlwaysCreateOnExistingFile = TRUE;
+ }
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ }
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ }
+
+ if(obj)
+ {
+ int i;
+ yfsd_WinFile *p;
+ openRead = openWrite =0;
+ openReadAllowed = openWriteAllowed = 1;
+
+ for(i = 0; i < MAX_WIN_FILE; i++)
+ {
+ p = &yfsd_winFile[i];
+
+ if(p->obj == obj)
+ {
+ if (p->readPermitted) openRead = 1;
+ if (p->writePermitted) openWrite = 1;
+ if (!p->shareRead) openReadAllowed = 0;
+ if (!p->shareWrite) openWriteAllowed = 0;
+ }
+
+ }
+
+ // Now we test if the share works out.
+
+ if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read
+ (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
+ (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
+ (!openWriteAllowed && writePermitted)) // same... write
+ {
+ //slf021220c begin Fix error code for new sharing mode check code.
+ SetLastError(ERROR_SHARING_VIOLATION);
+ //slf021220c end Fix error code for new sharing mode check code.
+ obj = NULL;
+ }
+
+
+ }
+ if(obj)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
+ f = yfsd_GetWinFile();
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
+ }
+
+ if(f)
+ {
+
+ handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
+
+ if(handle != INVALID_HANDLE_VALUE)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
+
+ if (fTruncateExistingFile)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));
+ yaffs_ResizeFile(obj,0);
+ }
+
+ if (fAlwaysCreateOnExistingFile)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));
+ obj->st_mode = mode;
+ obj->dirty = 1;
+ yaffs_ResizeFile(obj,0);
+ yaffs_FlushFile(obj,1);
+ }
+
+ f->obj = obj;
+ f->offset = 0;
+ f->writePermitted = writePermitted;
+ //slf021220d begin oops typo.
+ f->readPermitted = readPermitted;
+ //slf021220d end oops typo.
+ f->shareRead= shareRead;
+ f->shareWrite = shareWrite;
+ f->myVolume = pVolume;
+ obj->inUse++;
+
+ modifiedTime[0] = obj->win_mtime[0];
+ modifiedTime[1] = obj->win_mtime[1];
+ objSize = yaffs_GetObjectFileLength(obj);
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
+ }
+ else
+ {
+ yfsd_PutWinFile(f);
+ RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
+ }
+
+ }
+
+ yfsd_UnlockYAFFS();
+
+ if(handle != INVALID_HANDLE_VALUE &&
+ fileCreated &&
+ pVolume->shellFunction)
+ {
+ FILECHANGEINFO fc;
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_CREATE;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+ fc.dwItem2 = 0;
+ fc.dwAttributes = mode;
+ yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ pVolume->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+
+ yfsd_ShellDirectoryChanged(pVolume,fpn);
+ }
+
+ if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
+ {
+ // Remember the name
+
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int slen;
+
+ yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
+ slen = wcslen(fpn);
+ f->fullName = malloc((slen+1)* sizeof(WCHAR));
+ if(f->fullName)
+ {
+ wcscpy(f->fullName,fpn);
+ }
+
+ }
+
+
+ return handle;
+
+}
+
+BOOL yfsd_DoReadFile(
+ PFILE pFile,
+ PVOID pBuffer,
+ DWORD cbRead,
+ PDWORD pcbRead)
+{
+
+ DWORD maxRead;
+ int nread = 0;
+ yaffs_Object *obj = NULL;
+
+
+ if(pcbRead)
+ {
+ *pcbRead = 0;
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
+ }
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ obj = pFile->obj;
+
+ if(yaffs_GetObjectFileLength(obj) > pFile->offset)
+ {
+ maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
+ }
+ else
+ {
+ maxRead = 0;
+ }
+
+ if(cbRead > maxRead)
+ {
+ cbRead = maxRead;
+ }
+
+ if(maxRead > 0)
+ {
+ nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
+ if(nread > 0)
+ {
+ pFile->offset += nread;
+
+ if(pcbRead)
+ {
+ *pcbRead = nread;
+ }
+ }
+ }
+ else
+ {
+ if(pcbRead)
+ {
+ *pcbRead = maxRead;
+ }
+ }
+
+
+ return nread < 0? FALSE : TRUE;
+
+}
+
+BOOL YFSD_ReadFile(
+ PFILE pFile,
+ PVOID pBuffer,
+ DWORD cbRead,
+ PDWORD pcbRead,
+ OVERLAPPED *pOverlapped ) //ignore
+{
+ BOOL result;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+
+ yfsd_UnlockYAFFS();
+
+ return result;
+}
+
+BOOL YFSD_ReadFileWithSeek(
+ PFILE pFile,
+ PVOID pBuffer,
+ DWORD cbRead,
+ PDWORD pcbRead,
+ OVERLAPPED *pOverlapped,
+ DWORD dwLowOffset,
+ DWORD dwHighOffset )
+{
+ BOOL result;
+ DWORD rememberedOffset;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
+
+ // To determine if paging is supported, the kernel calls this with all parameters except pFile
+ // being zero.
+ if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
+ {
+ return TRUE; // paging suppported
+ //return FALSE; // paging not supported
+ }
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ rememberedOffset = pFile->offset;
+
+ pFile->offset = dwLowOffset;
+ // ignore high offset for now
+
+ result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
+
+ //pFile->offset = rememberedOffset;
+
+ yfsd_UnlockYAFFS();
+
+ return result;
+
+
+}
+
+
+BOOL yfsd_DoWriteFile(
+ PFILE pFile,
+ PCVOID pBuffer,
+ DWORD cbWrite,
+ PDWORD pcbWritten)
+{
+ int nwritten = 0;
+ yaffs_Object *obj = NULL;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if(!pFile->writePermitted)
+ {
+ *pcbWritten = 0;
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ obj = pFile->obj;
+
+ *pcbWritten = 0;
+
+
+ nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
+ if(nwritten >= 0)
+ {
+ pFile->offset += nwritten;
+ *pcbWritten = nwritten;
+ }
+ if(nwritten != cbWrite)
+ {
+ SetLastError(ERROR_DISK_FULL);
+ }
+
+
+ return nwritten != cbWrite? FALSE : TRUE;
+}
+
+
+BOOL YFSD_WriteFile(
+ PFILE pFile,
+ PCVOID pBuffer,
+ DWORD cbWrite,
+ PDWORD pcbWritten,
+ OVERLAPPED *pOverlapped )
+{
+ BOOL result;
+
+ yfsd_LockYAFFS();
+ RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
+
+ result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+
+ yfsd_UnlockYAFFS();
+
+ return result;
+}
+
+BOOL YFSD_WriteFileWithSeek(
+ PFILE pFile,
+ PCVOID pBuffer,
+ DWORD cbWrite,
+ PDWORD pcbWritten,
+ OVERLAPPED *pOverlapped,
+ DWORD dwLowOffset,
+ DWORD dwHighOffset )
+{
+ BOOL result;
+ DWORD rememberedOffset;
+ RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
+
+
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ rememberedOffset = pFile->offset;
+
+ pFile->offset = dwLowOffset;
+ // ignore high offset for now
+
+ result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
+
+ //pFile->offset = rememberedOffset;
+
+ yfsd_UnlockYAFFS();
+
+ return result;
+}
+
+DWORD YFSD_SetFilePointer(
+ PFILE pFile,
+ LONG lDistanceToMove,
+ PLONG pDistanceToMoveHigh,
+ DWORD dwMoveMethod )
+{
+ // ignore high offset for now
+
+ DWORD offset = 0xFFFFFFFF;
+ DWORD oldPos;
+ int fileSize;
+ int seekNegative = 0;
+
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return offset;
+ }
+
+ yfsd_LockYAFFS();
+
+
+ oldPos = pFile->offset;
+
+ if(dwMoveMethod == FILE_BEGIN)
+ {
+ if(lDistanceToMove >= 0)
+ {
+ offset = pFile->offset = lDistanceToMove;
+ }
+ else
+ {
+ seekNegative = 1;
+ }
+ }
+ else if(dwMoveMethod == FILE_END)
+ {
+ fileSize = yaffs_GetObjectFileLength(pFile->obj);
+ if(fileSize >= 0 &&
+ (fileSize + lDistanceToMove) >= 0)
+ {
+ offset = pFile->offset = fileSize + lDistanceToMove;
+ }
+ else
+ {
+ seekNegative = 1;
+ }
+ }
+ else if(dwMoveMethod == FILE_CURRENT)
+ {
+ if(pFile->offset + lDistanceToMove >= 0)
+ {
+ offset = pFile->offset = pFile->offset + lDistanceToMove;
+ }
+ else
+ {
+ seekNegative = 1;
+ }
+ }
+
+ if(seekNegative)
+ {
+ SetLastError(ERROR_NEGATIVE_SEEK);
+
+ }
+
+ yfsd_UnlockYAFFS();
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
+ dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
+
+ return offset;
+
+}
+
+DWORD YFSD_GetFileSize(
+ PFILE pFile,
+ PDWORD pFileSizeHigh )
+{
+ int fileSize;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
+
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return -1;
+ }
+
+ yfsd_LockYAFFS();
+
+ fileSize = yaffs_GetObjectFileLength(pFile->obj);
+
+ yfsd_UnlockYAFFS();
+ if(pFileSizeHigh)
+ *pFileSizeHigh = 0;
+
+ return fileSize;
+
+}
+
+
+BOOL YFSD_GetFileInformationByHandle(
+ PFILE pFile,
+ PBY_HANDLE_FILE_INFORMATION pFileInfo )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
+
+ if(!pFile || !pFile->obj || !pFileInfo)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
+ yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
+ yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
+ yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
+ pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
+ pFileInfo->nFileSizeHigh = 0;
+ pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
+ pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
+ pFileInfo->nFileIndexHigh = 0;
+ pFileInfo->nFileIndexLow = pFile->obj->objectId;
+ pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
+
+ yfsd_UnlockYAFFS();
+
+ return TRUE;
+}
+
+BOOL YFSD_FlushFileBuffers(PFILE pFile )
+{
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ yaffs_FlushFile(pFile->obj,1);
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+
+ yfsd_UnlockYAFFS();
+
+ if(vol && vol->shellFunction && nameExists)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
+
+
+ return TRUE;
+}
+
+BOOL YFSD_GetFileTime(
+ PFILE pFile,
+ FILETIME *pCreation,
+ FILETIME *pLastAccess,
+ FILETIME *pLastWrite )
+{
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+
+ if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
+ if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
+ if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
+
+ yfsd_UnlockYAFFS();
+
+ return TRUE;
+}
+
+BOOL YFSD_SetFileTime(
+ PFILE pFile,
+ CONST FILETIME *pCreation,
+ CONST FILETIME *pLastAccess,
+ CONST FILETIME *pLastWrite )
+{
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ int result = FALSE;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+
+ yfsd_LockYAFFS();
+
+ if(pCreation)
+ {
+ yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
+ pFile->obj->dirty = 1;
+ }
+ if(pLastAccess)
+ {
+ yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
+ pFile->obj->dirty = 1;
+ }
+ if(pLastWrite)
+ {
+ yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
+ pFile->obj->dirty = 1;
+ }
+ if(pCreation || pLastAccess || pLastWrite)
+ {
+ result = yaffs_FlushFile(pFile->obj,0);
+ }
+
+ if(result)
+ {
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+ }
+
+ yfsd_UnlockYAFFS();
+
+ // Call shell function
+ if(nameExists && result && vol && vol->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
+
+ return TRUE;
+}
+
+BOOL YFSD_SetEndOfFile(
+PFILE pFile )
+{
+
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+ static unsigned char zeros[512];
+
+ int result;
+ BOOL retVal = FALSE;
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
+
+ if(!pFile || !pFile->obj)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ yfsd_LockYAFFS();
+ result = yaffs_ResizeFile(pFile->obj,pFile->offset);
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
+
+ // Resize only works if we're shortening the file.
+ // If the result is shorter than the offset, then we need to write zeros....
+ //
+ if(result != pFile->offset)
+ {
+ if(result < pFile->offset)
+ {
+
+ int nBytes = pFile->offset - result;
+ int thisWriteSize;
+ int written;
+ BOOL ok = TRUE;
+
+ memset(zeros,0,512);
+
+ pFile->offset = result;
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
+ while(nBytes > 0 && ok)
+ {
+ thisWriteSize = (nBytes > 512) ? 512 : nBytes;
+
+ ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);
+ if(written != thisWriteSize)
+ {
+ ok = FALSE;
+ }
+
+ nBytes -= thisWriteSize;
+ }
+
+ retVal = ok;
+ }
+ else
+ {
+
+ SetLastError(ERROR_ACCESS_DENIED);
+ retVal = FALSE;
+ }
+ }
+ else
+ {
+ retVal = TRUE;
+ }
+ if(retVal)
+ {
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+ }
+
+
+ yfsd_UnlockYAFFS();
+
+ if(nameExists && retVal && vol && vol->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
+
+
+
+ return retVal;
+}
+
+BOOL YFSD_DeviceIoControl(
+ PFILE pFile,
+ DWORD dwIoControlCode,
+ PVOID pInBuf,
+ DWORD nInBufSize,
+ PVOID pOutBuf,
+ DWORD nOutBufSize,
+ PDWORD pBytesReturned,
+ OVERLAPPED *pOverlapped )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
+
+ return FALSE;
+}
+
+BOOL YFSD_CloseFile( PFILE pFile )
+{
+ WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
+ int nameExists = 0;
+ yfsd_Volume *vol = NULL;
+ DWORD attribs = 0;
+ DWORD objSize = 0;
+ DWORD mtime[2];
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
+
+ yfsd_LockYAFFS();
+
+ if(!pFile)
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
+ }
+ else
+ {
+ if(pFile->obj)
+ {
+ pFile->obj->inUse--;
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
+ yaffs_FlushFile(pFile->obj,1);
+ attribs = yfsd_GetObjectWinAttributes(pFile->obj);
+ objSize = yaffs_GetObjectFileLength(pFile->obj);
+ mtime[0] = pFile->obj->win_mtime[0];
+ mtime[1] = pFile->obj->win_mtime[1];
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
+ if(pFile->fullName)
+ {
+ wcscpy(fpn,pFile->fullName);
+ nameExists = 1;
+ }
+ vol = pFile->myVolume;
+ yfsd_PutWinFile(pFile);
+ }
+ else
+ {
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
+ }
+
+ }
+ yfsd_UnlockYAFFS();
+
+
+ if(nameExists && vol && vol->shellFunction)
+ {
+ FILECHANGEINFO fc;
+
+ fc.cbSize = sizeof(FILECHANGEINFO);
+ fc.wEventId = SHCNE_UPDATEITEM;
+ fc.uFlags = SHCNF_PATH;
+ fc.dwItem1 = (DWORD)fpn;
+ fc.dwItem2 = 0;
+ fc.dwAttributes = attribs;
+ yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
+ fc.nFileSize = objSize;
+
+ vol->shellFunction(&fc);
+ RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
+ //yfsd_ShellDirectoryChanged(vol,fpn);
+ }
+
+
+
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
+
+ return TRUE;
+
+}
+
+
+BOOL YFSD_CloseVolume(PVOLUME pVolume )
+{
+ RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
+ yfsd_FlushAllFiles();
+ return TRUE;
+}
+