2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
\r
3 * yaffsfsd.c: The FSD layer for the WinCE version of YAFFS.
\r
5 * Copyright (C) 2002 Trimble Navigation Ltd.
\r
7 * Created by Charles Manning <charles.manning@trimble.co.nz>
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License version 2 as
\r
11 * published by the Free Software Foundation.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
16 * General Public License for more details. You should have received a
\r
17 * copy of the GNU General Public License along with this program;
\r
18 * if not, write to the Free Software Foundation, Inc.,
\r
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
21 * $Id: yaffsfsd.c,v 1.1 2002-11-08 07:30:00 charles Exp $
\r
25 #include <yaffs_guts.h>
28 #define MAX_WIN_FILE 200
29 #define YFSD_NAME_LENGTH 128
30 #define YFSD_FULL_PATH_NAME_SIZE 500
33 #define YFSD_DISK_NAME L"Disk"
34 #define YFSD_BOOT_NAME L"Boot"
36 #define PARTITION_START_NUMBER (1280)
39 //#define DISABLE_BOOT_PARTITION
\r
41 unsigned yaffs_traceMask=0xffffffff;
48 DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
53 SHELLFILECHANGEFUNC_t shellFunction;
65 yfsd_Volume *myVolume;
69 struct yfsd_FoundObjectStruct
72 struct yfsd_FoundObjectStruct *next;
75 typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
80 char pattern[YFSD_NAME_LENGTH+1];
81 yaffs_FoundObject *foundObjects;
86 #define PSEARCH yfsd_WinFind*
88 #define PVOLUME yfsd_Volume*
89 #define PFILE yfsd_WinFile*
96 static yfsd_Volume disk_volume;
97 static yfsd_Volume boot_volume;
99 static CRITICAL_SECTION yaffsLock;
100 static CRITICAL_SECTION winFileLock;
102 static int yaffsLockInited = 0;
104 static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
107 static yfsd_SetGuards(void)
110 for(i = 0; i < 100; i++)
112 yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
116 static void yfsd_CheckGuards(void)
120 for(i = found = 0; i < 100 && !found; i++)
122 if(yfsd_volume.guard0[i] != i)
124 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
127 if(yfsd_volume.guard1[i] != i)
129 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
136 void yfsd_LockWinFiles(void)
138 //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
139 EnterCriticalSection(&winFileLock);
141 void yfsd_UnlockWinFiles(void)
143 //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
144 LeaveCriticalSection(&winFileLock);
149 void yfsd_LockYAFFS(void)
151 //yfsd_CheckGuards();
152 //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
154 EnterCriticalSection(&yaffsLock);
155 //RETAILMSG (MSGSTATE, (L" locked\r\n"));
157 void yfsd_UnlockYAFFS(void)
159 //yfsd_CheckGuards();
160 //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
161 LeaveCriticalSection(&yaffsLock);
163 //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
167 void yfsd_InitialiseWinFiles(void)
171 RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
173 InitializeCriticalSection(&winFileLock);
176 for(i = 0; i < MAX_WIN_FILE; i++)
178 yfsd_winFile[i].isopen = 0;
180 yfsd_UnlockWinFiles();
183 yfsd_WinFile * yfsd_GetWinFile(void)
186 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
190 for(i = 0; i < MAX_WIN_FILE; i++)
192 if(!yfsd_winFile[i].isopen)
194 yfsd_winFile[i].isopen = 1;
195 yfsd_winFile[i].writePermitted = 0;
196 yfsd_winFile[i].dirty = 0;
197 yfsd_winFile[i].fullName = NULL;
198 yfsd_winFile[i].obj = NULL;
200 yfsd_UnlockWinFiles();
201 return &yfsd_winFile[i];
205 yfsd_UnlockWinFiles();
207 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
212 void yfsd_PutWinFile(yfsd_WinFile *f)
214 RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
224 yfsd_UnlockWinFiles();
229 void yfsd_FlushAllFiles(void)
232 RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
236 for(i = 0; i < MAX_WIN_FILE; i++)
238 if(yfsd_winFile[i].isopen &&
241 yaffs_FlushFile(yfsd_winFile[i].obj);
244 yfsd_UnlockWinFiles();
248 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
251 // todo check for bounds
253 wcscat(fpn,vol->volName);
254 if(pathName[0] != '\\')
258 wcscat(fpn,pathName);
265 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
267 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
270 wft->dwLowDateTime = target[0];
271 wft->dwHighDateTime = target[1];
275 void yfsd_NullWinFileTime(FILETIME *wft)
277 wft->dwLowDateTime = 0;
278 wft->dwHighDateTime = 0;
281 void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
283 target[0] = wft->dwLowDateTime;
284 target[1] = wft->dwHighDateTime;
287 void yfsd_WinFileTimeNow(__u32 target[2])
293 SystemTimeToFileTime(&st,&ft);
294 yfsd_WinFileTimeToU32s(&ft,target);
297 // Cut down the name to the parent directory, then inform the shell of
298 // a change to the directory.
299 void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
303 wcscpy(str,fullPathName);
313 // Curveball if the name is a directory (ie. we're doing an update of
314 // a directory because we added a directory item). , then it might end in a \
315 // which we must toss first
316 if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
322 // Ok, now strip back...
324 while(i >= 0 && str[i] != '\\' && str[i] != '/')
330 if(pVolume->shellFunction)
334 fc.cbSize = sizeof(FILECHANGEINFO);
335 fc.wEventId = SHCNE_UPDATEDIR;
336 fc.uFlags = SHCNF_PATH;
337 fc.dwItem1 = (DWORD)str;
340 yfsd_NullWinFileTime(&fc.ftModified);
343 pVolume->shellFunction(&fc);
344 RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
352 // Minimal name test for now
\r
353 BOOL yfsd_NameIsValid (const char *name)
\r
355 int length = strlen(name);
\r
357 return (length > 0 && length <= YFSD_NAME_LENGTH);
\r
362 // Wince understands the following attributes of any use to YAFFS:
370 // Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
372 // It also understands NORMAL. If no other flag is set, then set NORMAL.
373 // If any of the above are set, then NORMAL must **not** be set.
374 // Ignore this and the WinCE Explorer barfs the file.
377 // in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
379 // The following are valid ones we get presented with,
\r
380 // but must filter out the stuff we don't unserstand
\r
381 //#define FILE_ATTRIBUTE_READONLY 0x00000001
\r
382 //#define FILE_ATTRIBUTE_HIDDEN 0x00000002
\r
383 //#define FILE_ATTRIBUTE_SYSTEM 0x00000004
\r
384 //#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
\r
385 //#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
\r
386 //#define FILE_ATTRIBUTE_INROM 0x00000040
\r
387 //#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
\r
388 //#define FILE_ATTRIBUTE_NORMAL 0x00000080
\r
389 //#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
\r
390 //#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
\r
391 //#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
\r
392 //#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
\r
393 //#define FILE_ATTRIBUTE_OFFLINE 0x00001000
\r
394 //#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
\r
395 //#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
\r
396 //#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
\r
399 BOOL yfsd_CheckValidAttributes(DWORD attribs)
\r
402 RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
\r
405 // If NORMAL, then nothing else
\r
406 if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
\r
408 if(attribs == FILE_ATTRIBUTE_NORMAL)
\r
411 // Check that the bits are in the valid set
\r
412 if(attribs & ~(0x3FE7))
\r
418 DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
423 result = obj->st_mode &
\r
424 (FILE_ATTRIBUTE_READONLY |
\r
425 FILE_ATTRIBUTE_ARCHIVE |
\r
426 FILE_ATTRIBUTE_HIDDEN |
\r
427 FILE_ATTRIBUTE_SYSTEM);
429 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
\r
431 if(result & ~FILE_ATTRIBUTE_NORMAL)
433 result &= ~FILE_ATTRIBUTE_NORMAL;
437 result = FILE_ATTRIBUTE_NORMAL;
447 * Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
448 * reached. Characters are copied from input into output until the above stop
449 * condition is reached - output is then given a '\0'. output must be at least
450 * as large as outSize
452 static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
456 /* strip any starting \'s */
457 //RETAILMSG(1, (L"\r\nParsing.. "));
458 while (*input == '\\' || *input == '/') input++, counter++;
460 for (; counter < outSize - 1; counter++)
462 if (*input == '\0' ||
463 ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'
465 counter = -1; // break & tell people we've run to the end
468 if (*input == '\\' || *input == '/')
470 //RETAILMSG(1, (L"%c", *input));
471 *output = (char) (*input);
477 // RETAILMSG(1, (L"\r\nOut %a\r\n", t));
483 * Since the notion of paths as WinCE sees them and as YAFFS sees them
484 * is different, we needed a helper function to search from the root of
485 * device along the string in path. The processed pointer is set to where
486 * abouts in the string the function was able to search up to.
488 yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
490 // a buffer to keep the current chunk of path we're talking about it
494 // the current object we are at
495 yaffs_Object *current;
497 RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
498 // start at the root of this device
499 current = yaffs_Root(device);
\r
504 // parse chunks until we run out
505 chunkSize = parseToNextSlash(path, pathChunk, 255);
506 // RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
509 // move the path pointer along
511 // try and find the next yaffs object by chunkname
512 current = yaffs_FindObjectByName(current, pathChunk);
520 for (counter = 0; counter < length; counter++)
522 // Get the rest of the string
523 processed[counter] = pathChunk[counter];
524 if (pathChunk[counter] == '\0')
528 RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
534 yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
536 yaffs_Object *obj = NULL;
537 yaffs_Object *parent = NULL;
538 char name[YFSD_NAME_LENGTH+1];
540 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
542 parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
544 if(parent && yfsd_NameIsValid(name))
546 obj = yaffs_FindObjectByName(parent,name);
549 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
554 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
556 RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
557 vol->volName = volName;
562 //Mount/initialise YAFFs here
563 ynandif_InitialiseNAND(&vol->dev);
565 vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
566 vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
567 vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
568 vol->dev.initialiseNAND = ynandif_InitialiseNAND;
569 vol->dev.startBlock = startBlock;
571 vol->dev.endBlock = endBlock;
573 // nBlocks is set the total size of the disk, not the partition
574 // vol->dev.nBlocks = endBlock - startBlock + 1;
576 // qnand_EraseAllBlocks(&vol->dev);
578 yaffs_GutsInitialise(&vol->dev);
579 RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
581 RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
582 vol->dev.startBlock,vol->dev.endBlock,
583 vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
587 for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
589 switch(vol->dev.blockInfo[i].blockState)
591 case YAFFS_BLOCK_STATE_DEAD:
593 RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
596 case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
597 case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
598 case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
599 case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
601 RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
606 RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",
607 deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
615 vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
624 SetLastError(ERROR_OUTOFMEMORY);
630 BOOL YFSD_MountDisk(HDSK hdsk)
632 int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
634 // Called to mount a disk.
635 // NB THis call might happen redundantly.
638 // If yaffs is not initialised, then call the
639 // initialisation function
641 RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
643 if (!yaffsLockInited)
645 InitializeCriticalSection(&yaffsLock);
646 yfsd_InitialiseWinFiles();
650 #ifdef DISABLE_BOOT_PARTITION
651 // Only want disk volume
652 YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
655 if(disk_volume.isMounted)
660 // Want both boot and disk
661 YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
662 YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
665 if(disk_volume.isMounted && boot_volume.isMounted)
675 // todo - get name from registry
680 BOOL YFSD_UnmountDisk(HDSK hdsk)
682 RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
684 yfsd_FlushAllFiles();
687 yaffs_Deinitialise(&disk_volume.dev);
688 yaffs_Deinitialise(&boot_volume.dev);
691 FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
692 FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
697 BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
699 // security attributes are ignored (should be NULL)
701 yaffs_Object *newDir = NULL;
702 yaffs_Object *parent = NULL;
703 char name[YFSD_NAME_LENGTH+1];
706 unsigned modifiedTime[2];
708 RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
712 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
714 if(parent && yfsd_NameIsValid(name))
716 newDir = yaffs_MknodDirectory(parent,name,0,0,0);
721 objSize = yaffs_GetObjectFileLength(newDir);
722 attribs = yfsd_GetObjectWinAttributes(newDir);
723 modifiedTime[0] = newDir->win_mtime[0];
\r
724 modifiedTime[1] = newDir->win_mtime[1];
\r
728 SetLastError(ERROR_PATH_NOT_FOUND);
733 // Call shell function to tell of new directory
734 if(newDir && pVolume->shellFunction)
737 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
739 fc.cbSize = sizeof(FILECHANGEINFO);
740 fc.wEventId = SHCNE_MKDIR;
741 fc.uFlags = SHCNF_PATH;
742 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
744 fc.dwAttributes = attribs;
745 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
746 fc.nFileSize = objSize;
748 pVolume->shellFunction(&fc);
749 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
751 //yfsd_ShellDirectoryChanged(pVolume,fpn);
755 if(parent && !newDir)
757 SetLastError(ERROR_DISK_FULL);
760 return newDir ? TRUE : FALSE;
764 BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
766 // Fails if directory is not empty
768 yaffs_Object *parent = NULL;
770 char name[YFSD_NAME_LENGTH+1];
772 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveObjectW (%s)\r\n", pathName));
776 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
779 SetLastError(ERROR_FILE_NOT_FOUND);
782 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
784 SetLastError(ERROR_ACCESS_DENIED);
789 SetLastError(ERROR_ACCESS_DENIED);
795 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
797 if(parent && yfsd_NameIsValid(name))
799 result = yaffs_Unlink(parent,name);
801 SetLastError(ERROR_ACCESS_DENIED);
807 return result ? TRUE : FALSE;
811 BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
814 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory\r\n"));
816 result = yfsd_RemoveObjectW(pVolume, pathName);
818 if(result && pVolume->shellFunction)
821 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
823 fc.cbSize = sizeof(FILECHANGEINFO);
824 fc.wEventId = SHCNE_RMDIR;
825 fc.uFlags = SHCNF_PATH;
826 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
829 yfsd_NullWinFileTime(&fc.ftModified);
832 pVolume->shellFunction(&fc);
833 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
835 yfsd_ShellDirectoryChanged(pVolume,fpn);
843 DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
845 yaffs_Object *obj = NULL;
847 DWORD result = 0xFFFFFFFF;
849 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
853 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
857 result = yfsd_GetObjectWinAttributes(obj);
861 SetLastError(ERROR_FILE_NOT_FOUND);
866 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
872 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
874 yaffs_Object *obj = NULL;
\r
881 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
\r
883 if(!yfsd_CheckValidAttributes(dwFileAttributes))
\r
885 SetLastError(ERROR_INVALID_PARAMETER);
\r
891 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
895 obj->st_mode = dwFileAttributes;
897 result = yaffs_FlushFile(obj);
\r
898 attribs = yfsd_GetObjectWinAttributes(obj);
\r
899 objSize = yaffs_GetObjectFileLength(obj);
\r
900 mtime[0] = obj->win_mtime[0];
\r
901 mtime[1] = obj->win_mtime[1];
\r
905 SetLastError(ERROR_FILE_NOT_FOUND);
910 if(result && pVolume->shellFunction)
913 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
915 fc.cbSize = sizeof(FILECHANGEINFO);
916 fc.wEventId = SHCNE_ATTRIBUTES;
917 fc.uFlags = SHCNF_PATH;
918 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
920 fc.dwAttributes = attribs;
921 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
922 fc.nFileSize = objSize;
924 pVolume->shellFunction(&fc);
925 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
927 //yfsd_ShellDirectoryChanged(pVolume,fpn);
935 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
938 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
940 result = yfsd_RemoveObjectW(pVolume, pwsFileName);
941 if(result && pVolume->shellFunction)
944 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
946 fc.cbSize = sizeof(FILECHANGEINFO);
947 fc.wEventId = SHCNE_DELETE;
948 fc.uFlags = SHCNF_PATH;
949 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
951 fc.dwAttributes = -1;
952 yfsd_NullWinFileTime(&fc.ftModified);
955 pVolume->shellFunction(&fc);
956 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
958 yfsd_ShellDirectoryChanged(pVolume,fpn);
964 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
966 yaffs_Object *newParent = NULL;
967 yaffs_Object *oldParent = NULL;
968 yaffs_Object *obj = NULL;
969 char oldName[YFSD_NAME_LENGTH+1];
970 char newName[YFSD_NAME_LENGTH+1];
977 RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
981 oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
982 newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
984 if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
986 result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
989 SetLastError(ERROR_FILE_NOT_FOUND);
992 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
995 objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
996 attribs = yfsd_GetObjectWinAttributes(obj);
997 objSize = yaffs_GetObjectFileLength(obj);
\r
998 mtime[0] = obj->win_mtime[0];
\r
999 mtime[1] = obj->win_mtime[1];
\r
1004 SetLastError(ERROR_PATH_NOT_FOUND);
1010 if(result && pVolume->shellFunction)
1013 WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
1014 WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
1016 fc.cbSize = sizeof(FILECHANGEINFO);
1017 fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
1018 fc.uFlags = SHCNF_PATH;
1019 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
1020 fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
1021 fc.dwAttributes = attribs;
1022 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1023 fc.nFileSize = objSize;
1025 pVolume->shellFunction(&fc);
1026 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1028 yfsd_ShellDirectoryChanged(pVolume,fpn1);
1029 yfsd_ShellDirectoryChanged(pVolume,fpn2);
1033 return result ? TRUE : FALSE;
1037 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1039 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
1043 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
1048 RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
1051 nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
1056 // Let's pretentd our clusters are the same size as eraseable blocks...
1057 *pBytesPerSector = 512;
1058 *pSectorsPerCluster =32;
1059 *pFreeClusters = nChunks/32;
1060 *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
1063 return (nChunks >= 0)? TRUE : FALSE;
1069 void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
1071 // Flags can be one of:
1072 // FSNOTIFY_POWER_ON: no action required
1073 // FSNOTIFY_POWER_OFF: flush all files
1074 // FSNOTIFY_DEVICE_ON: no action required
1076 RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
1077 if(dwFlags == FSNOTIFY_POWER_OFF)
1079 yfsd_FlushAllFiles();
1085 BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
1087 RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
1089 pVolume->shellFunction = pfn;
1098 int iMatch(const char a, const char b)
1100 if (a == '?' || b == '?')
1102 return (toupper(a) == toupper(b));
1105 void pString(const char *inp)
1107 while (*inp) RETAILMSG(1, (L"%c", *inp++));
1110 int regularMatch(const char *regexp, const char *str)
1113 // RETAILMSG(1, (L" "));
1115 // RETAILMSG(1, (L"\r\n"));
1117 if (*regexp == 0 && *str == 0)
1119 //RETAILMSG(1, (L"Match!\r\n"));
1125 if (*regexp == 0) // end of the expression is a *, we must match
1127 //RETAILMSG(1, (L"Match!\r\n"));
1130 while (!iMatch(*regexp, *str)) // throw away chars from str until we match
1132 if (*str == 0) // if we're not at the end
1134 // if we have .* left to match, but the str is finished then match it OK
1135 if (regexp[0] == '.' && regexp[1] == '*')
1137 //RETAILMSG(1, (L"Match!\r\n"));
1142 // the extension failed the match
1143 //RETAILMSG(1, (L"No Match!\r\n"));
1149 // right now we should either eat more characters, or try to match
1150 return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
1152 // compare chars until we hit another *, or we fail
1153 while (iMatch(*regexp, *str))
1155 if (*regexp == 0 && *str == 0)
1157 //RETAILMSG(1, (L"Match!\r\n"));
1164 if (*regexp == 0 && *str == 0)
1166 //RETAILMSG(1, (L"Match!\r\n"));
1171 return regularMatch(regexp, str);
1173 //RETAILMSG(1, (L"No Match!\r\n"));
1178 void yfsd_DeleteFinder(PSEARCH pSearch)
1180 if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
1182 yaffs_FoundObject *it;
1183 yaffs_FoundObject *temp;
1185 it = pSearch->foundObjects;
1195 pSearch->foundObjects = NULL;
1198 pSearch->dir->inUse--;
1202 BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
1204 //Iterate through the current list of objs already found and return true if already exists.
1205 //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
1208 yaffs_FoundObject *it;
1209 it = pSearch->foundObjects;
1212 while(it->next != NULL) //iterate through singly linked list.
1224 //Add the item to the list.
1225 //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
1226 it->next = malloc(sizeof(yaffs_FoundObject));
1227 it->next->next = NULL;
1238 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1241 struct list_head *i;
1246 char name[YAFFS_MAX_NAME_LENGTH+1];
1248 if(!pSearch->foundObjects)
1250 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1251 pSearch->foundObjects->next = NULL;
1252 pSearch->foundObjects->obj = 0;
1259 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1262 l = list_entry(i, yaffs_Object,siblings);
1264 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1266 if(regularMatch(pSearch->pattern,name))
1268 if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
1273 //pSearch->currentPos++;
1275 // fill out find data
1277 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1279 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1280 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1281 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1283 pfd->nFileSizeHigh = 0;
1284 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1285 pfd->dwOID = 0; // wtf is this???
1287 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1289 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1290 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1291 l->variant.fileVariant.scannedFileSize));
1307 SetLastError(ERROR_NO_MORE_FILES);
1315 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
\r
1318 struct list_head *i;
\r
1322 char name[YAFFS_MAX_NAME_LENGTH+1];
\r
1324 if(!pSearch->foundObjects)
\r
1326 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
\r
1327 pSearch->foundObjects->next = NULL;
\r
1328 pSearch->foundObjects->obj = 0;
\r
1334 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
\r
1337 l = list_entry(i, yaffs_Object,siblings);
\r
1338 if(!yfsd_ObjectAlreadyFound(pSearch,l))
\r
1340 // Only look at things we have not looked at already
\r
1341 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
\r
1343 if(regularMatch(pSearch->pattern,name))
\r
1346 // fill out find data
\r
1348 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
\r
1350 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
\r
1351 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
\r
1352 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
\r
1354 pfd->nFileSizeHigh = 0;
\r
1355 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
\r
1356 pfd->dwOID = 0; // wtf is this???
\r
1358 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
\r
1360 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
\r
1361 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
\r
1362 l->variant.fileVariant.scannedFileSize));
\r
1372 yfsd_UnlockYAFFS();
\r
1377 SetLastError(ERROR_NO_MORE_FILES);
\r
1384 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
1387 // Create a search context, register it, and do the first search
1390 HANDLE h = INVALID_HANDLE_VALUE;
1393 RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
1395 pSearch = malloc(sizeof(yfsd_WinFind));
1398 SetLastError(ERROR_OUTOFMEMORY);
1405 pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
1406 pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
1409 pSearch->dir->inUse++;
1424 found = yfsd_DoFindFile(pSearch,pfd);
1429 h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
1432 if(h == INVALID_HANDLE_VALUE && pSearch)
1434 yfsd_DeleteFinder(pSearch);
1435 SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
1443 BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
1445 RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
1450 return yfsd_DoFindFile(pSearch,pfd);
1453 BOOL YFSD_FindClose( PSEARCH pSearch )
1455 RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
1460 yfsd_DeleteFinder(pSearch);
1465 HANDLE YFSD_CreateFileW(
1471 PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
1473 DWORD dwFlagsAndAttributes,
1474 HANDLE hTemplateFile ) // ignore
1478 yaffs_Object *parent = NULL;
1479 yaffs_Object *obj = NULL;
1480 char name[YFSD_NAME_LENGTH+1];
1482 yfsd_WinFile *f = NULL;
1483 HANDLE handle = INVALID_HANDLE_VALUE;
1484 unsigned modifiedTime[2];
1487 BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
1489 BOOL fileCreated = FALSE;
1492 mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags
1495 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
1498 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
1502 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
1505 if(!yfsd_CheckValidAttributes(mode))
\r
1507 SetLastError(ERROR_INVALID_PARAMETER);
\r
1514 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
1517 if(parent && yfsd_NameIsValid(name))
1521 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1522 if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
\r
1524 // Naughty, naughty. Don't do file ops on directories
\r
1525 SetLastError(ERROR_ACCESS_DENIED);
\r
1526 fileCreated = FALSE;
\r
1529 else if(dwCreate == CREATE_NEW)
1531 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
1533 obj = yaffs_MknodFile(parent,name,mode,0,0);
1535 SetLastError(ERROR_DISK_FULL);
1538 else if( dwCreate == OPEN_ALWAYS)
1540 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1543 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
1544 obj = yaffs_MknodFile(parent,name,mode,0,0);
1546 SetLastError(ERROR_DISK_FULL);
1552 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
1555 else if(dwCreate == OPEN_EXISTING)
1557 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
1558 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1560 SetLastError(ERROR_FILE_NOT_FOUND);
1562 else if(dwCreate == TRUNCATE_EXISTING)
1564 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
1565 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1568 yaffs_ResizeFile(obj,0);
1572 SetLastError(ERROR_FILE_NOT_FOUND);
1575 else if(dwCreate == CREATE_ALWAYS)
1577 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1581 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
1582 obj = yaffs_MknodFile(parent,name,mode,0,0);
1584 SetLastError(ERROR_DISK_FULL);
1589 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
1590 obj->st_mode = mode;
1592 yaffs_ResizeFile(obj,0);
1593 yaffs_FlushFile(obj);
1598 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
1599 SetLastError(ERROR_INVALID_PARAMETER);
1604 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
1605 SetLastError(ERROR_PATH_NOT_FOUND);
1610 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
1611 f = yfsd_GetWinFile();
1615 RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
1621 handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
1623 if(handle != INVALID_HANDLE_VALUE)
1625 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
1628 f->writePermitted = writePermitted;
1629 f->myVolume = pVolume;
1632 modifiedTime[0] = obj->win_mtime[0];
\r
1633 modifiedTime[1] = obj->win_mtime[1];
\r
1634 objSize = yaffs_GetObjectFileLength(obj);
1635 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
1640 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
1647 if(handle != INVALID_HANDLE_VALUE &&
1649 pVolume->shellFunction)
1652 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1654 fc.cbSize = sizeof(FILECHANGEINFO);
1655 fc.wEventId = SHCNE_CREATE;
1656 fc.uFlags = SHCNF_PATH;
1657 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1659 fc.dwAttributes = mode;
1660 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
1661 fc.nFileSize = objSize;
1663 pVolume->shellFunction(&fc);
1664 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1666 yfsd_ShellDirectoryChanged(pVolume,fpn);
1669 if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
1671 // Remember the name
1673 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1676 yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1678 f->fullName = malloc((slen+1)* sizeof(WCHAR));
1681 wcscpy(f->fullName,fpn);
1691 BOOL yfsd_DoReadFile(
1700 yaffs_Object *obj = NULL;
1709 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
1712 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
1714 if(!pFile || !pFile->obj)
1716 SetLastError(ERROR_INVALID_HANDLE);
1722 if(yaffs_GetObjectFileLength(obj) > pFile->offset)
1724 maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
1731 if(cbRead > maxRead)
1738 nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
1741 pFile->offset += nread;
\r
1753 *pcbRead = maxRead;
\r
1758 return nread < 0? FALSE : TRUE;
1767 OVERLAPPED *pOverlapped ) //ignore
1771 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
1773 if(!pFile || !pFile->obj)
1775 SetLastError(ERROR_INVALID_HANDLE);
1781 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
1788 BOOL YFSD_ReadFileWithSeek(
1793 OVERLAPPED *pOverlapped,
1795 DWORD dwHighOffset )
1798 DWORD rememberedOffset;
1800 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
1802 // To determine if paging is supported, the kernel calls this with all parameters except pFile
1804 if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
1806 return TRUE; // paging suppported
1807 //return FALSE; // paging not supported
1810 if(!pFile || !pFile->obj)
1812 SetLastError(ERROR_INVALID_HANDLE);
1818 rememberedOffset = pFile->offset;
1820 pFile->offset = dwLowOffset;
1821 // ignore high offset for now
1823 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
1825 //pFile->offset = rememberedOffset;
\r
1835 BOOL yfsd_DoWriteFile(
1842 yaffs_Object *obj = NULL;
1844 RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
1846 if(!pFile || !pFile->obj)
1848 SetLastError(ERROR_INVALID_HANDLE);
1852 if(!pFile->writePermitted)
1855 SetLastError(ERROR_ACCESS_DENIED);
1864 nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
1867 pFile->offset += nwritten;
1868 *pcbWritten = nwritten;
1870 if(nwritten != cbWrite)
1872 SetLastError(ERROR_DISK_FULL);
1876 return nwritten != cbWrite? FALSE : TRUE;
1880 BOOL YFSD_WriteFile(
1885 OVERLAPPED *pOverlapped )
1890 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
1892 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
1899 BOOL YFSD_WriteFileWithSeek(
1904 OVERLAPPED *pOverlapped,
1906 DWORD dwHighOffset )
1909 DWORD rememberedOffset;
1910 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
1914 if(!pFile || !pFile->obj)
1916 SetLastError(ERROR_INVALID_HANDLE);
1922 rememberedOffset = pFile->offset;
\r
1924 pFile->offset = dwLowOffset;
1925 // ignore high offset for now
1927 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
1929 //pFile->offset = rememberedOffset;
\r
1936 DWORD YFSD_SetFilePointer(
1938 LONG lDistanceToMove,
1939 PLONG pDistanceToMoveHigh,
1940 DWORD dwMoveMethod )
1942 // ignore high offset for now
1944 DWORD offset = 0xFFFFFFFF;
1947 int seekNegative = 0;
1950 if(!pFile || !pFile->obj)
1952 SetLastError(ERROR_INVALID_HANDLE);
1959 oldPos = pFile->offset;
1961 if(dwMoveMethod == FILE_BEGIN)
1963 if(lDistanceToMove >= 0)
1965 offset = pFile->offset = lDistanceToMove;
1972 else if(dwMoveMethod == FILE_END)
1974 fileSize = yaffs_GetObjectFileLength(pFile->obj);
1976 (fileSize + lDistanceToMove) >= 0)
1978 offset = pFile->offset = fileSize + lDistanceToMove;
1985 else if(dwMoveMethod == FILE_CURRENT)
1987 if(pFile->offset + lDistanceToMove >= 0)
1989 offset = pFile->offset = pFile->offset + lDistanceToMove;
1999 SetLastError(ERROR_NEGATIVE_SEEK);
2005 RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
2006 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
2012 DWORD YFSD_GetFileSize(
2014 PDWORD pFileSizeHigh )
2018 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
2021 if(!pFile || !pFile->obj)
2023 SetLastError(ERROR_INVALID_HANDLE);
2029 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2031 yfsd_UnlockYAFFS();
\r
2040 BOOL YFSD_GetFileInformationByHandle(
2042 PBY_HANDLE_FILE_INFORMATION pFileInfo )
2044 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
2046 if(!pFile || !pFile->obj || !pFileInfo)
2048 SetLastError(ERROR_INVALID_HANDLE);
2054 pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2055 yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
\r
2056 yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
\r
2057 yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
\r
2058 pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
\r
2059 pFileInfo->nFileSizeHigh = 0;
\r
2060 pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
\r
2061 pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
\r
2062 pFileInfo->nFileIndexHigh = 0;
\r
2063 pFileInfo->nFileIndexLow = pFile->obj->objectId;
\r
2070 BOOL YFSD_FlushFileBuffers(PFILE pFile )
2072 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2073 int nameExists = 0;
\r
2074 yfsd_Volume *vol = NULL;
\r
2075 DWORD attribs = 0;
\r
2076 DWORD objSize = 0;
\r
2080 RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
2082 if(!pFile || !pFile->obj)
2084 SetLastError(ERROR_INVALID_HANDLE);
2090 yaffs_FlushFile(pFile->obj);
\r
2091 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2092 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2093 mtime[0] = pFile->obj->win_mtime[0];
\r
2094 mtime[1] = pFile->obj->win_mtime[1];
\r
2095 if(pFile->fullName)
\r
2097 wcscpy(fpn,pFile->fullName);
\r
2100 vol = pFile->myVolume;
\r
2104 if(vol && vol->shellFunction && nameExists)
\r
2106 FILECHANGEINFO fc;
\r
2108 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2109 fc.wEventId = SHCNE_UPDATEITEM;
\r
2110 fc.uFlags = SHCNF_PATH;
\r
2111 fc.dwItem1 = (DWORD)fpn;
\r
2113 fc.dwAttributes = attribs;
\r
2114 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2115 fc.nFileSize = objSize;
\r
2117 vol->shellFunction(&fc);
\r
2118 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2119 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2126 BOOL YFSD_GetFileTime(
2128 FILETIME *pCreation,
2129 FILETIME *pLastAccess,
2130 FILETIME *pLastWrite )
2133 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
2134 if(!pFile || !pFile->obj)
2136 SetLastError(ERROR_INVALID_HANDLE);
2142 if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
2143 if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
2144 if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
2151 BOOL YFSD_SetFileTime(
2153 CONST FILETIME *pCreation,
2154 CONST FILETIME *pLastAccess,
2155 CONST FILETIME *pLastWrite )
2157 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2158 int nameExists = 0;
\r
2160 yfsd_Volume *vol = NULL;
\r
2161 DWORD attribs = 0;
\r
2162 DWORD objSize = 0;
\r
2166 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
2168 if(!pFile || !pFile->obj)
2170 SetLastError(ERROR_INVALID_HANDLE);
2179 yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
\r
2180 pFile->obj->dirty = 1;
\r
2184 yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
\r
2185 pFile->obj->dirty = 1;
\r
2189 yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
\r
2190 pFile->obj->dirty = 1;
2192 if(pCreation || pLastAccess || pLastWrite)
2194 result = yaffs_FlushFile(pFile->obj);
2199 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2200 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2201 mtime[0] = pFile->obj->win_mtime[0];
\r
2202 mtime[1] = pFile->obj->win_mtime[1];
\r
2203 if(pFile->fullName)
\r
2205 wcscpy(fpn,pFile->fullName);
\r
2208 vol = pFile->myVolume;
\r
2213 // Call shell function
2214 if(nameExists && result && vol && vol->shellFunction)
\r
2216 FILECHANGEINFO fc;
\r
2218 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2219 fc.wEventId = SHCNE_UPDATEITEM;
\r
2220 fc.uFlags = SHCNF_PATH;
\r
2221 fc.dwItem1 = (DWORD)fpn;
\r
2223 fc.dwAttributes = attribs;
\r
2224 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2225 fc.nFileSize = objSize;
\r
2227 vol->shellFunction(&fc);
\r
2228 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2229 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2235 BOOL YFSD_SetEndOfFile(
2239 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2240 int nameExists = 0;
\r
2241 yfsd_Volume *vol = NULL;
\r
2242 DWORD attribs = 0;
\r
2243 DWORD objSize = 0;
\r
2245 static unsigned char zeros[512];
2248 BOOL retVal = FALSE;
2250 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
2252 if(!pFile || !pFile->obj)
2254 SetLastError(ERROR_INVALID_HANDLE);
2259 result = yaffs_ResizeFile(pFile->obj,pFile->offset);
2261 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
2263 // Resize only works if we're shortening the file.
2264 // If the result is shorter than the offset, then we need to write zeros....
2266 if(result != pFile->offset)
2268 if(result < pFile->offset)
2271 int nBytes = pFile->offset - result;
2276 memset(zeros,0,512);
2278 pFile->offset = result;
2279 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
2280 while(nBytes > 0 && ok)
2282 thisWriteSize = (nBytes > 512) ? 512 : nBytes;
2284 ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);
2285 if(written != thisWriteSize)
2290 nBytes -= thisWriteSize;
2298 SetLastError(ERROR_ACCESS_DENIED);
2308 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2309 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2310 mtime[0] = pFile->obj->win_mtime[0];
\r
2311 mtime[1] = pFile->obj->win_mtime[1];
\r
2312 if(pFile->fullName)
\r
2314 wcscpy(fpn,pFile->fullName);
\r
2317 vol = pFile->myVolume;
\r
2321 yfsd_UnlockYAFFS();
\r
2323 if(nameExists && retVal && vol && vol->shellFunction)
\r
2325 FILECHANGEINFO fc;
\r
2327 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2328 fc.wEventId = SHCNE_UPDATEITEM;
\r
2329 fc.uFlags = SHCNF_PATH;
\r
2330 fc.dwItem1 = (DWORD)fpn;
\r
2332 fc.dwAttributes = attribs;
\r
2333 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2334 fc.nFileSize = objSize;
\r
2336 vol->shellFunction(&fc);
\r
2337 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2338 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2341 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
2348 BOOL YFSD_DeviceIoControl(
2350 DWORD dwIoControlCode,
2355 PDWORD pBytesReturned,
2356 OVERLAPPED *pOverlapped )
2358 RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
2363 BOOL YFSD_CloseFile( PFILE pFile )
2365 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2367 yfsd_Volume *vol = NULL;
2372 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
2378 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
2384 pFile->obj->inUse--;
2385 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
2386 yaffs_FlushFile(pFile->obj);
2387 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2388 objSize = yaffs_GetObjectFileLength(pFile->obj);
2389 mtime[0] = pFile->obj->win_mtime[0];
\r
2390 mtime[1] = pFile->obj->win_mtime[1];
\r
2391 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
2394 wcscpy(fpn,pFile->fullName);
2397 vol = pFile->myVolume;
2398 yfsd_PutWinFile(pFile);
2402 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
2409 if(nameExists && vol && vol->shellFunction)
2413 fc.cbSize = sizeof(FILECHANGEINFO);
2414 fc.wEventId = SHCNE_UPDATEITEM;
2415 fc.uFlags = SHCNF_PATH;
2416 fc.dwItem1 = (DWORD)fpn;
2418 fc.dwAttributes = attribs;
2419 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2420 fc.nFileSize = objSize;
2422 vol->shellFunction(&fc);
2423 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2424 //yfsd_ShellDirectoryChanged(vol,fpn);
2429 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
2436 BOOL YFSD_CloseVolume(PVOLUME pVolume )
2438 RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
2439 yfsd_FlushAllFiles();